Commit 95aff94d authored by shigemi miura's avatar shigemi miura

NGA対応

parent 7f096f00
...@@ -62,12 +62,9 @@ ...@@ -62,12 +62,9 @@
02C3E5D12AFCC16800AF7837 /* ChatTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C3E5D02AFCC16800AF7837 /* ChatTitleView.swift */; }; 02C3E5D12AFCC16800AF7837 /* ChatTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C3E5D02AFCC16800AF7837 /* ChatTitleView.swift */; };
02C3E6092AFDF30000AF7837 /* ChatMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C3E6082AFDF30000AF7837 /* ChatMemberView.swift */; }; 02C3E6092AFDF30000AF7837 /* ChatMemberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02C3E6082AFDF30000AF7837 /* ChatMemberView.swift */; };
02CD068F2AE6535F005F8D8F /* MapSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD068E2AE6535F005F8D8F /* MapSource.swift */; }; 02CD068F2AE6535F005F8D8F /* MapSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD068E2AE6535F005F8D8F /* MapSource.swift */; };
02CD06912AE6536B005F8D8F /* LayerEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD06902AE6536B005F8D8F /* LayerEnum.swift */; };
02CD06932AE88970005F8D8F /* ServerSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD06922AE88970005F8D8F /* ServerSession.swift */; }; 02CD06932AE88970005F8D8F /* ServerSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD06922AE88970005F8D8F /* ServerSession.swift */; };
02CD06952AE895F5005F8D8F /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD06942AE895F5005F8D8F /* APIError.swift */; }; 02CD06952AE895F5005F8D8F /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CD06942AE895F5005F8D8F /* APIError.swift */; };
02CE4D7F2ADE42A9002E79BC /* MenuContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D7E2ADE42A9002E79BC /* MenuContentView.swift */; }; 02CE4D7F2ADE42A9002E79BC /* MenuContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D7E2ADE42A9002E79BC /* MenuContentView.swift */; };
02CE4D832ADE672B002E79BC /* MapTaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D822ADE672B002E79BC /* MapTaskView.swift */; };
02CE4D852ADF6295002E79BC /* TaskSwitchingMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D842ADF6295002E79BC /* TaskSwitchingMenuView.swift */; };
02CE4D872ADF62A7002E79BC /* EcaListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D862ADF62A7002E79BC /* EcaListView.swift */; }; 02CE4D872ADF62A7002E79BC /* EcaListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D862ADF62A7002E79BC /* EcaListView.swift */; };
02CE4D892ADF62E1002E79BC /* EcaSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D882ADF62E1002E79BC /* EcaSettingView.swift */; }; 02CE4D892ADF62E1002E79BC /* EcaSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4D882ADF62E1002E79BC /* EcaSettingView.swift */; };
02CE4DC82ADF97E8002E79BC /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4DC72ADF97E8002E79BC /* View+Extensions.swift */; }; 02CE4DC82ADF97E8002E79BC /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02CE4DC72ADF97E8002E79BC /* View+Extensions.swift */; };
...@@ -92,17 +89,21 @@ ...@@ -92,17 +89,21 @@
D52D213F2AEBB7D700324D58 /* RegisteredEca.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52D213E2AEBB7D700324D58 /* RegisteredEca.swift */; }; D52D213F2AEBB7D700324D58 /* RegisteredEca.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52D213E2AEBB7D700324D58 /* RegisteredEca.swift */; };
D52D21412AEDE18F00324D58 /* EcaCoordinatesTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52D21402AEDE18F00324D58 /* EcaCoordinatesTable.swift */; }; D52D21412AEDE18F00324D58 /* EcaCoordinatesTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52D21402AEDE18F00324D58 /* EcaCoordinatesTable.swift */; };
D536F6712B678D8900A5BCF9 /* ReqUploadImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D536F6702B678D8900A5BCF9 /* ReqUploadImage.swift */; }; D536F6712B678D8900A5BCF9 /* ReqUploadImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = D536F6702B678D8900A5BCF9 /* ReqUploadImage.swift */; };
D5384AFC2B306CEF006228C6 /* TermsView.html in Resources */ = {isa = PBXBuildFile; fileRef = D5384AFB2B306CEF006228C6 /* TermsView.html */; }; D539F3302C1809790088E609 /* NgaTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D539F32F2C1809790088E609 /* NgaTask.swift */; };
D5384AFE2B3121F2006228C6 /* PrivacyView.html in Resources */ = {isa = PBXBuildFile; fileRef = D5384AFD2B3121F2006228C6 /* PrivacyView.html */; };
D53B97262B341867000B3D29 /* AboutAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53B97252B341867000B3D29 /* AboutAppView.swift */; }; D53B97262B341867000B3D29 /* AboutAppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53B97252B341867000B3D29 /* AboutAppView.swift */; };
D545FC742B09C74300F206D0 /* AlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D545FC732B09C74300F206D0 /* AlertManager.swift */; }; D545FC742B09C74300F206D0 /* AlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D545FC732B09C74300F206D0 /* AlertManager.swift */; };
D545FC762B09C81300F206D0 /* PushNotificationTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D545FC752B09C81300F206D0 /* PushNotificationTypes.swift */; }; D545FC762B09C81300F206D0 /* PushNotificationTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D545FC752B09C81300F206D0 /* PushNotificationTypes.swift */; };
D546B0132C197BB50058CD98 /* MapInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D546B0122C197BB50058CD98 /* MapInformation.swift */; };
D54A5FD72B8F10B500F3A9D6 /* StatusEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54A5FD62B8F10B500F3A9D6 /* StatusEnum.swift */; }; D54A5FD72B8F10B500F3A9D6 /* StatusEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54A5FD62B8F10B500F3A9D6 /* StatusEnum.swift */; };
D54D174B2B35137A00A0EAA5 /* LocalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54D174A2B35137A00A0EAA5 /* LocalWebView.swift */; }; D54D174B2B35137A00A0EAA5 /* LocalWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54D174A2B35137A00A0EAA5 /* LocalWebView.swift */; };
D54D17512B35923400A0EAA5 /* GetManualUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54D17502B35923400A0EAA5 /* GetManualUrl.swift */; }; D54D17512B35923400A0EAA5 /* GetManualUrl.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54D17502B35923400A0EAA5 /* GetManualUrl.swift */; };
D55135202B15B030007B66B1 /* SetEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D551351F2B15B030007B66B1 /* SetEcaArea.swift */; }; D55135202B15B030007B66B1 /* SetEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D551351F2B15B030007B66B1 /* SetEcaArea.swift */; };
D55135222B15C062007B66B1 /* GetEcaList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55135212B15C062007B66B1 /* GetEcaList.swift */; }; D55135222B15C062007B66B1 /* GetEcaList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55135212B15C062007B66B1 /* GetEcaList.swift */; };
D55135242B15C3BF007B66B1 /* DeleteEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55135232B15C3BF007B66B1 /* DeleteEcaArea.swift */; }; D55135242B15C3BF007B66B1 /* DeleteEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55135232B15C3BF007B66B1 /* DeleteEcaArea.swift */; };
D57905FE2C1C069000AF797C /* SetNgaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57905FD2C1C069000AF797C /* SetNgaArea.swift */; };
D57906002C1C06F600AF797C /* SessionNgaList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57905FF2C1C06F600AF797C /* SessionNgaList.swift */; };
D57906022C1C0CFB00AF797C /* ReqNgaList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57906012C1C0CFB00AF797C /* ReqNgaList.swift */; };
D58E06D02C1D1AF20039F22C /* GetNgaList.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E06CF2C1D1AF20039F22C /* GetNgaList.swift */; };
D58E1F502B142A260092D8FE /* EcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1F4F2B142A260092D8FE /* EcaArea.swift */; }; D58E1F502B142A260092D8FE /* EcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1F4F2B142A260092D8FE /* EcaArea.swift */; };
D58E1F522B142A3F0092D8FE /* ResEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1F512B142A3F0092D8FE /* ResEcaArea.swift */; }; D58E1F522B142A3F0092D8FE /* ResEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1F512B142A3F0092D8FE /* ResEcaArea.swift */; };
D58E1F542B142A510092D8FE /* SessionEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1F532B142A510092D8FE /* SessionEcaArea.swift */; }; D58E1F542B142A510092D8FE /* SessionEcaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D58E1F532B142A510092D8FE /* SessionEcaArea.swift */; };
...@@ -124,6 +125,12 @@ ...@@ -124,6 +125,12 @@
D5B493A12B48E930008B3620 /* privacy.html in Resources */ = {isa = PBXBuildFile; fileRef = D5B4939F2B48E930008B3620 /* privacy.html */; }; D5B493A12B48E930008B3620 /* privacy.html in Resources */ = {isa = PBXBuildFile; fileRef = D5B4939F2B48E930008B3620 /* privacy.html */; };
D5B493A42B48EE50008B3620 /* Manual in Resources */ = {isa = PBXBuildFile; fileRef = D5B493A32B48EE50008B3620 /* Manual */; }; D5B493A42B48EE50008B3620 /* Manual in Resources */ = {isa = PBXBuildFile; fileRef = D5B493A32B48EE50008B3620 /* Manual */; };
D5B803282B3B988E003B32AD /* AppVersionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B803272B3B988E003B32AD /* AppVersionModel.swift */; }; D5B803282B3B988E003B32AD /* AppVersionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5B803272B3B988E003B32AD /* AppVersionModel.swift */; };
D5C7822F2BF88755001EBB3A /* MenuTaskView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C7822E2BF88755001EBB3A /* MenuTaskView.swift */; };
D5C7823A2BFB4C2A001EBB3A /* NgaNotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C782392BFB4C2A001EBB3A /* NgaNotificationView.swift */; };
D5C7823C2BFB4CEF001EBB3A /* FuelSwitchingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C7823B2BFB4CEF001EBB3A /* FuelSwitchingView.swift */; };
D5C782462BFB55F0001EBB3A /* DeleteNgaArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C782432BFB55F0001EBB3A /* DeleteNgaArea.swift */; };
D5C782472BFB55F0001EBB3A /* RegistereNga.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C782442BFB55F0001EBB3A /* RegistereNga.swift */; };
D5C782492BFC2DA2001EBB3A /* NgaSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C782482BFC2DA2001EBB3A /* NgaSettingView.swift */; };
D5CB6F992B02088C00EC2010 /* ResShipStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB6F982B02088C00EC2010 /* ResShipStatus.swift */; }; D5CB6F992B02088C00EC2010 /* ResShipStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB6F982B02088C00EC2010 /* ResShipStatus.swift */; };
D5CB6F9B2B021C4F00EC2010 /* LocationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB6F9A2B021C4F00EC2010 /* LocationViewModel.swift */; }; D5CB6F9B2B021C4F00EC2010 /* LocationViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB6F9A2B021C4F00EC2010 /* LocationViewModel.swift */; };
D5CB6F9F2B0220A700EC2010 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB6F9E2B0220A700EC2010 /* ErrorView.swift */; }; D5CB6F9F2B0220A700EC2010 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5CB6F9E2B0220A700EC2010 /* ErrorView.swift */; };
...@@ -227,12 +234,9 @@ ...@@ -227,12 +234,9 @@
02C3E5D02AFCC16800AF7837 /* ChatTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ChatTitleView.swift; path = SailAssist/Chat/View/ChatTitleView.swift; sourceTree = SOURCE_ROOT; }; 02C3E5D02AFCC16800AF7837 /* ChatTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ChatTitleView.swift; path = SailAssist/Chat/View/ChatTitleView.swift; sourceTree = SOURCE_ROOT; };
02C3E6082AFDF30000AF7837 /* ChatMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ChatMemberView.swift; path = Sailassist/Chat/View/ChatMemberView.swift; sourceTree = SOURCE_ROOT; }; 02C3E6082AFDF30000AF7837 /* ChatMemberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ChatMemberView.swift; path = Sailassist/Chat/View/ChatMemberView.swift; sourceTree = SOURCE_ROOT; };
02CD068E2AE6535F005F8D8F /* MapSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapSource.swift; sourceTree = "<group>"; }; 02CD068E2AE6535F005F8D8F /* MapSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapSource.swift; sourceTree = "<group>"; };
02CD06902AE6536B005F8D8F /* LayerEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayerEnum.swift; sourceTree = "<group>"; };
02CD06922AE88970005F8D8F /* ServerSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSession.swift; sourceTree = "<group>"; }; 02CD06922AE88970005F8D8F /* ServerSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSession.swift; sourceTree = "<group>"; };
02CD06942AE895F5005F8D8F /* APIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = "<group>"; }; 02CD06942AE895F5005F8D8F /* APIError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = "<group>"; };
02CE4D7E2ADE42A9002E79BC /* MenuContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuContentView.swift; sourceTree = "<group>"; }; 02CE4D7E2ADE42A9002E79BC /* MenuContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuContentView.swift; sourceTree = "<group>"; };
02CE4D822ADE672B002E79BC /* MapTaskView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTaskView.swift; sourceTree = "<group>"; };
02CE4D842ADF6295002E79BC /* TaskSwitchingMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskSwitchingMenuView.swift; sourceTree = "<group>"; };
02CE4D862ADF62A7002E79BC /* EcaListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EcaListView.swift; sourceTree = "<group>"; }; 02CE4D862ADF62A7002E79BC /* EcaListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EcaListView.swift; sourceTree = "<group>"; };
02CE4D882ADF62E1002E79BC /* EcaSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EcaSettingView.swift; sourceTree = "<group>"; }; 02CE4D882ADF62E1002E79BC /* EcaSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EcaSettingView.swift; sourceTree = "<group>"; };
02CE4DC72ADF97E8002E79BC /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; }; 02CE4DC72ADF97E8002E79BC /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
...@@ -265,18 +269,22 @@ ...@@ -265,18 +269,22 @@
D52D213E2AEBB7D700324D58 /* RegisteredEca.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RegisteredEca.swift; path = Sailassist/ECA/RegisteredEca.swift; sourceTree = SOURCE_ROOT; }; D52D213E2AEBB7D700324D58 /* RegisteredEca.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RegisteredEca.swift; path = Sailassist/ECA/RegisteredEca.swift; sourceTree = SOURCE_ROOT; };
D52D21402AEDE18F00324D58 /* EcaCoordinatesTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EcaCoordinatesTable.swift; path = Sailassist/ECA/EcaCoordinatesTable.swift; sourceTree = SOURCE_ROOT; }; D52D21402AEDE18F00324D58 /* EcaCoordinatesTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = EcaCoordinatesTable.swift; path = Sailassist/ECA/EcaCoordinatesTable.swift; sourceTree = SOURCE_ROOT; };
D536F6702B678D8900A5BCF9 /* ReqUploadImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReqUploadImage.swift; path = Sailassist/Json/ReqUploadImage.swift; sourceTree = SOURCE_ROOT; }; D536F6702B678D8900A5BCF9 /* ReqUploadImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReqUploadImage.swift; path = Sailassist/Json/ReqUploadImage.swift; sourceTree = SOURCE_ROOT; };
D5384AFB2B306CEF006228C6 /* TermsView.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = TermsView.html; path = SailAssist/html/TermsView.html; sourceTree = SOURCE_ROOT; }; D539F32F2C1809790088E609 /* NgaTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NgaTask.swift; sourceTree = "<group>"; };
D5384AFD2B3121F2006228C6 /* PrivacyView.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = PrivacyView.html; path = SailAssist/html/PrivacyView.html; sourceTree = SOURCE_ROOT; };
D53ACA752B0AECF8008DCB18 /* Sailassist.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Sailassist.entitlements; path = Sailassist/Sailassist.entitlements; sourceTree = "<group>"; }; D53ACA752B0AECF8008DCB18 /* Sailassist.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Sailassist.entitlements; path = Sailassist/Sailassist.entitlements; sourceTree = "<group>"; };
D53B97252B341867000B3D29 /* AboutAppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AboutAppView.swift; path = Sailassist/Login/AboutAppView.swift; sourceTree = SOURCE_ROOT; }; D53B97252B341867000B3D29 /* AboutAppView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AboutAppView.swift; path = Sailassist/Login/AboutAppView.swift; sourceTree = SOURCE_ROOT; };
D545FC732B09C74300F206D0 /* AlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AlertManager.swift; path = Sailassist/VoiceManager/AlertManager.swift; sourceTree = SOURCE_ROOT; }; D545FC732B09C74300F206D0 /* AlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AlertManager.swift; path = Sailassist/VoiceManager/AlertManager.swift; sourceTree = SOURCE_ROOT; };
D545FC752B09C81300F206D0 /* PushNotificationTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PushNotificationTypes.swift; path = Sailassist/DataSource/PushNotificationTypes.swift; sourceTree = SOURCE_ROOT; }; D545FC752B09C81300F206D0 /* PushNotificationTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PushNotificationTypes.swift; path = Sailassist/DataSource/PushNotificationTypes.swift; sourceTree = SOURCE_ROOT; };
D546B0122C197BB50058CD98 /* MapInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MapInformation.swift; path = Sailassist/Map/MapInformation.swift; sourceTree = SOURCE_ROOT; };
D54A5FD62B8F10B500F3A9D6 /* StatusEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StatusEnum.swift; path = Sailassist/SharingData/StatusEnum.swift; sourceTree = SOURCE_ROOT; }; D54A5FD62B8F10B500F3A9D6 /* StatusEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = StatusEnum.swift; path = Sailassist/SharingData/StatusEnum.swift; sourceTree = SOURCE_ROOT; };
D54D174A2B35137A00A0EAA5 /* LocalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LocalWebView.swift; path = Sailassist/Menu/View/LocalWebView.swift; sourceTree = SOURCE_ROOT; }; D54D174A2B35137A00A0EAA5 /* LocalWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LocalWebView.swift; path = Sailassist/Menu/View/LocalWebView.swift; sourceTree = SOURCE_ROOT; };
D54D17502B35923400A0EAA5 /* GetManualUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GetManualUrl.swift; path = Sailassist/Menu/GetManualUrl.swift; sourceTree = SOURCE_ROOT; }; D54D17502B35923400A0EAA5 /* GetManualUrl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GetManualUrl.swift; path = Sailassist/Menu/GetManualUrl.swift; sourceTree = SOURCE_ROOT; };
D551351F2B15B030007B66B1 /* SetEcaArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SetEcaArea.swift; path = Sailassist/ECA/SetEcaArea.swift; sourceTree = SOURCE_ROOT; }; D551351F2B15B030007B66B1 /* SetEcaArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SetEcaArea.swift; path = Sailassist/ECA/SetEcaArea.swift; sourceTree = SOURCE_ROOT; };
D55135212B15C062007B66B1 /* GetEcaList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GetEcaList.swift; path = Sailassist/ECA/GetEcaList.swift; sourceTree = SOURCE_ROOT; }; D55135212B15C062007B66B1 /* GetEcaList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GetEcaList.swift; path = Sailassist/ECA/GetEcaList.swift; sourceTree = SOURCE_ROOT; };
D55135232B15C3BF007B66B1 /* DeleteEcaArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeleteEcaArea.swift; path = Sailassist/ECA/DeleteEcaArea.swift; sourceTree = SOURCE_ROOT; }; D55135232B15C3BF007B66B1 /* DeleteEcaArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeleteEcaArea.swift; path = Sailassist/ECA/DeleteEcaArea.swift; sourceTree = SOURCE_ROOT; };
D57905FD2C1C069000AF797C /* SetNgaArea.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetNgaArea.swift; sourceTree = "<group>"; };
D57905FF2C1C06F600AF797C /* SessionNgaList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = SessionNgaList.swift; path = Sailassist/ServerSession/SessionNgaList.swift; sourceTree = SOURCE_ROOT; };
D57906012C1C0CFB00AF797C /* ReqNgaList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReqNgaList.swift; path = Sailassist/Json/ReqNgaList.swift; sourceTree = SOURCE_ROOT; };
D58E06CF2C1D1AF20039F22C /* GetNgaList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetNgaList.swift; sourceTree = "<group>"; };
D58E1F4F2B142A260092D8FE /* EcaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EcaArea.swift; path = Sailassist/ECA/EcaArea.swift; sourceTree = SOURCE_ROOT; }; D58E1F4F2B142A260092D8FE /* EcaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = EcaArea.swift; path = Sailassist/ECA/EcaArea.swift; sourceTree = SOURCE_ROOT; };
D58E1F512B142A3F0092D8FE /* ResEcaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResEcaArea.swift; path = Sailassist/Json/ResEcaArea.swift; sourceTree = SOURCE_ROOT; }; D58E1F512B142A3F0092D8FE /* ResEcaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ResEcaArea.swift; path = Sailassist/Json/ResEcaArea.swift; sourceTree = SOURCE_ROOT; };
D58E1F532B142A510092D8FE /* SessionEcaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SessionEcaArea.swift; path = Sailassist/ServerSession/SessionEcaArea.swift; sourceTree = SOURCE_ROOT; }; D58E1F532B142A510092D8FE /* SessionEcaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SessionEcaArea.swift; path = Sailassist/ServerSession/SessionEcaArea.swift; sourceTree = SOURCE_ROOT; };
...@@ -298,6 +306,12 @@ ...@@ -298,6 +306,12 @@
D5B4939F2B48E930008B3620 /* privacy.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = privacy.html; path = Sailassist/html/privacy.html; sourceTree = SOURCE_ROOT; }; D5B4939F2B48E930008B3620 /* privacy.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = privacy.html; path = Sailassist/html/privacy.html; sourceTree = SOURCE_ROOT; };
D5B493A32B48EE50008B3620 /* Manual */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Manual; path = Sailassist/html/Manual; sourceTree = SOURCE_ROOT; }; D5B493A32B48EE50008B3620 /* Manual */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Manual; path = Sailassist/html/Manual; sourceTree = SOURCE_ROOT; };
D5B803272B3B988E003B32AD /* AppVersionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppVersionModel.swift; path = Sailassist/AppVersionModel.swift; sourceTree = SOURCE_ROOT; }; D5B803272B3B988E003B32AD /* AppVersionModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AppVersionModel.swift; path = Sailassist/AppVersionModel.swift; sourceTree = SOURCE_ROOT; };
D5C7822E2BF88755001EBB3A /* MenuTaskView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MenuTaskView.swift; path = Sailassist/Map/Task/View/MenuTaskView.swift; sourceTree = SOURCE_ROOT; };
D5C782392BFB4C2A001EBB3A /* NgaNotificationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NgaNotificationView.swift; path = Sailassist/Map/Task/View/NgaNotificationView.swift; sourceTree = SOURCE_ROOT; };
D5C7823B2BFB4CEF001EBB3A /* FuelSwitchingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FuelSwitchingView.swift; path = Sailassist/Map/Task/View/FuelSwitchingView.swift; sourceTree = SOURCE_ROOT; };
D5C782432BFB55F0001EBB3A /* DeleteNgaArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteNgaArea.swift; sourceTree = "<group>"; };
D5C782442BFB55F0001EBB3A /* RegistereNga.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RegistereNga.swift; sourceTree = "<group>"; };
D5C782482BFC2DA2001EBB3A /* NgaSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = NgaSettingView.swift; path = Sailassist/Map/Task/View/NgaSettingView.swift; sourceTree = SOURCE_ROOT; };
D5CB6F982B02088C00EC2010 /* ResShipStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ResShipStatus.swift; path = Sailassist/Json/ResShipStatus.swift; sourceTree = SOURCE_ROOT; }; D5CB6F982B02088C00EC2010 /* ResShipStatus.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ResShipStatus.swift; path = Sailassist/Json/ResShipStatus.swift; sourceTree = SOURCE_ROOT; };
D5CB6F9A2B021C4F00EC2010 /* LocationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LocationViewModel.swift; path = Sailassist/LocationViewModel.swift; sourceTree = SOURCE_ROOT; }; D5CB6F9A2B021C4F00EC2010 /* LocationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LocationViewModel.swift; path = Sailassist/LocationViewModel.swift; sourceTree = SOURCE_ROOT; };
D5CB6F9E2B0220A700EC2010 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ErrorView.swift; path = Sailassist/ErrorView.swift; sourceTree = SOURCE_ROOT; }; D5CB6F9E2B0220A700EC2010 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ErrorView.swift; path = Sailassist/ErrorView.swift; sourceTree = SOURCE_ROOT; };
...@@ -371,6 +385,7 @@ ...@@ -371,6 +385,7 @@
020B98122AD8C3140029DE4C /* SailAssist */ = { 020B98122AD8C3140029DE4C /* SailAssist */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D5C782452BFB55F0001EBB3A /* NGA */,
D5384AFF2B3121FA006228C6 /* html */, D5384AFF2B3121FA006228C6 /* html */,
D545FC722B09C6DA00F206D0 /* VoiceManager */, D545FC722B09C6DA00F206D0 /* VoiceManager */,
D51AA4052B099F6D00EBBDD4 /* DataSource */, D51AA4052B099F6D00EBBDD4 /* DataSource */,
...@@ -457,8 +472,8 @@ ...@@ -457,8 +472,8 @@
0227890F2AE6028000A87787 /* Task */, 0227890F2AE6028000A87787 /* Task */,
02CE4DD92ADFBA72002E79BC /* MapRepresentable.swift */, 02CE4DD92ADFBA72002E79BC /* MapRepresentable.swift */,
02CD068E2AE6535F005F8D8F /* MapSource.swift */, 02CD068E2AE6535F005F8D8F /* MapSource.swift */,
02CD06902AE6536B005F8D8F /* LayerEnum.swift */,
D5258C9A2B03401E00365276 /* MonitoringRoute.swift */, D5258C9A2B03401E00365276 /* MonitoringRoute.swift */,
D546B0122C197BB50058CD98 /* MapInformation.swift */,
); );
path = Map; path = Map;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -563,10 +578,12 @@ ...@@ -563,10 +578,12 @@
022789102AE6028400A87787 /* View */ = { 022789102AE6028400A87787 /* View */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
02CE4D822ADE672B002E79BC /* MapTaskView.swift */, D5C7823B2BFB4CEF001EBB3A /* FuelSwitchingView.swift */,
02CE4D842ADF6295002E79BC /* TaskSwitchingMenuView.swift */, D5C782392BFB4C2A001EBB3A /* NgaNotificationView.swift */,
D5C7822E2BF88755001EBB3A /* MenuTaskView.swift */,
02CE4D862ADF62A7002E79BC /* EcaListView.swift */, 02CE4D862ADF62A7002E79BC /* EcaListView.swift */,
02CE4D882ADF62E1002E79BC /* EcaSettingView.swift */, 02CE4D882ADF62E1002E79BC /* EcaSettingView.swift */,
D5C782482BFC2DA2001EBB3A /* NgaSettingView.swift */,
); );
path = View; path = View;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -596,6 +613,7 @@ ...@@ -596,6 +613,7 @@
02F4DB662B2C173F00E86C41 /* SessionGetManualUrl.swift */, 02F4DB662B2C173F00E86C41 /* SessionGetManualUrl.swift */,
D58EF2442B901D3900FB784C /* SessionInformation.swift */, D58EF2442B901D3900FB784C /* SessionInformation.swift */,
D58EF2482B90562B00FB784C /* GetInformation.swift */, D58EF2482B90562B00FB784C /* GetInformation.swift */,
D57905FF2C1C06F600AF797C /* SessionNgaList.swift */,
); );
path = ServerSession; path = ServerSession;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -774,10 +792,24 @@ ...@@ -774,10 +792,24 @@
D5FCEF562B4789A8009A81D0 /* ResAckMessage.swift */, D5FCEF562B4789A8009A81D0 /* ResAckMessage.swift */,
D5FCEF582B4789D2009A81D0 /* ResChatMode.swift */, D5FCEF582B4789D2009A81D0 /* ResChatMode.swift */,
D536F6702B678D8900A5BCF9 /* ReqUploadImage.swift */, D536F6702B678D8900A5BCF9 /* ReqUploadImage.swift */,
D57906012C1C0CFB00AF797C /* ReqNgaList.swift */,
); );
path = Json; path = Json;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D5C782452BFB55F0001EBB3A /* NGA */ = {
isa = PBXGroup;
children = (
D5C782432BFB55F0001EBB3A /* DeleteNgaArea.swift */,
D5C782442BFB55F0001EBB3A /* RegistereNga.swift */,
D539F32F2C1809790088E609 /* NgaTask.swift */,
D57905FD2C1C069000AF797C /* SetNgaArea.swift */,
D58E06CF2C1D1AF20039F22C /* GetNgaList.swift */,
);
name = NGA;
path = Sailassist/NGA;
sourceTree = SOURCE_ROOT;
};
D5EA86482AF2139D0032E810 /* Location */ = { D5EA86482AF2139D0032E810 /* Location */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -992,7 +1024,7 @@ ...@@ -992,7 +1024,7 @@
D55135222B15C062007B66B1 /* GetEcaList.swift in Sources */, D55135222B15C062007B66B1 /* GetEcaList.swift in Sources */,
D52D21412AEDE18F00324D58 /* EcaCoordinatesTable.swift in Sources */, D52D21412AEDE18F00324D58 /* EcaCoordinatesTable.swift in Sources */,
02A1DE2F2AFB4AA0005BCF55 /* ChatInputView.swift in Sources */, 02A1DE2F2AFB4AA0005BCF55 /* ChatInputView.swift in Sources */,
02CD06912AE6536B005F8D8F /* LayerEnum.swift in Sources */, D57905FE2C1C069000AF797C /* SetNgaArea.swift in Sources */,
020B98532AD919180029DE4C /* LoginTypeSelectView.swift in Sources */, 020B98532AD919180029DE4C /* LoginTypeSelectView.swift in Sources */,
D52D213F2AEBB7D700324D58 /* RegisteredEca.swift in Sources */, D52D213F2AEBB7D700324D58 /* RegisteredEca.swift in Sources */,
02CD06952AE895F5005F8D8F /* APIError.swift in Sources */, 02CD06952AE895F5005F8D8F /* APIError.swift in Sources */,
...@@ -1002,9 +1034,12 @@ ...@@ -1002,9 +1034,12 @@
022A98202AF8B8960079C55A /* LocationCalculation.swift in Sources */, 022A98202AF8B8960079C55A /* LocationCalculation.swift in Sources */,
D5258CA72B03988600365276 /* ReqTaskList.swift in Sources */, D5258CA72B03988600365276 /* ReqTaskList.swift in Sources */,
D5CB6F9B2B021C4F00EC2010 /* LocationViewModel.swift in Sources */, D5CB6F9B2B021C4F00EC2010 /* LocationViewModel.swift in Sources */,
D5C7823C2BFB4CEF001EBB3A /* FuelSwitchingView.swift in Sources */,
D58E06D02C1D1AF20039F22C /* GetNgaList.swift in Sources */,
02CE4DC82ADF97E8002E79BC /* View+Extensions.swift in Sources */, 02CE4DC82ADF97E8002E79BC /* View+Extensions.swift in Sources */,
025F99742B2C125900C9A18A /* ResGetManualUrl.swift in Sources */, 025F99742B2C125900C9A18A /* ResGetManualUrl.swift in Sources */,
D58E1F542B142A510092D8FE /* SessionEcaArea.swift in Sources */, D58E1F542B142A510092D8FE /* SessionEcaArea.swift in Sources */,
D5C7823A2BFB4C2A001EBB3A /* NgaNotificationView.swift in Sources */,
025C28002B034A1900BADC49 /* PDFViewer.swift in Sources */, 025C28002B034A1900BADC49 /* PDFViewer.swift in Sources */,
02C3E6092AFDF30000AF7837 /* ChatMemberView.swift in Sources */, 02C3E6092AFDF30000AF7837 /* ChatMemberView.swift in Sources */,
020B98412AD8C3810029DE4C /* LoginView.swift in Sources */, 020B98412AD8C3810029DE4C /* LoginView.swift in Sources */,
...@@ -1020,20 +1055,23 @@ ...@@ -1020,20 +1055,23 @@
02F4DB672B2C173F00E86C41 /* SessionGetManualUrl.swift in Sources */, 02F4DB672B2C173F00E86C41 /* SessionGetManualUrl.swift in Sources */,
D5AE351B2AEBA66A00059889 /* ResLogin.swift in Sources */, D5AE351B2AEBA66A00059889 /* ResLogin.swift in Sources */,
D592D5252B0F16CA00B91A1C /* ReqMessage.swift in Sources */, D592D5252B0F16CA00B91A1C /* ReqMessage.swift in Sources */,
02CE4D832ADE672B002E79BC /* MapTaskView.swift in Sources */, D5C782472BFB55F0001EBB3A /* RegistereNga.swift in Sources */,
02CE4DCC2ADFA03F002E79BC /* SelectedTabModel.swift in Sources */, 02CE4DCC2ADFA03F002E79BC /* SelectedTabModel.swift in Sources */,
D5258C9B2B03401E00365276 /* MonitoringRoute.swift in Sources */, D5258C9B2B03401E00365276 /* MonitoringRoute.swift in Sources */,
D57906022C1C0CFB00AF797C /* ReqNgaList.swift in Sources */,
020B98162AD8C3150029DE4C /* ContentView.swift in Sources */, 020B98162AD8C3150029DE4C /* ContentView.swift in Sources */,
020B98632ADD14E50029DE4C /* ChatView.swift in Sources */, 020B98632ADD14E50029DE4C /* ChatView.swift in Sources */,
02CE4DDA2ADFBA72002E79BC /* MapRepresentable.swift in Sources */, 02CE4DDA2ADFBA72002E79BC /* MapRepresentable.swift in Sources */,
020B985E2ADCFF130029DE4C /* PreferencesKey.swift in Sources */, 020B985E2ADCFF130029DE4C /* PreferencesKey.swift in Sources */,
0227890C2AE22E0B00A87787 /* SharingData.swift in Sources */, 0227890C2AE22E0B00A87787 /* SharingData.swift in Sources */,
D57906002C1C06F600AF797C /* SessionNgaList.swift in Sources */,
020B984D2AD9178F0029DE4C /* ScannerViewModel.swift in Sources */, 020B984D2AD9178F0029DE4C /* ScannerViewModel.swift in Sources */,
020B98142AD8C3140029DE4C /* SailassistApp.swift in Sources */, 020B98142AD8C3140029DE4C /* SailassistApp.swift in Sources */,
02CE4D852ADF6295002E79BC /* TaskSwitchingMenuView.swift in Sources */, D546B0132C197BB50058CD98 /* MapInformation.swift in Sources */,
D5CB6F9F2B0220A700EC2010 /* ErrorView.swift in Sources */, D5CB6F9F2B0220A700EC2010 /* ErrorView.swift in Sources */,
D5CB6F992B02088C00EC2010 /* ResShipStatus.swift in Sources */, D5CB6F992B02088C00EC2010 /* ResShipStatus.swift in Sources */,
023DB8282B1429E400B351CF /* NotificationContentView.swift in Sources */, 023DB8282B1429E400B351CF /* NotificationContentView.swift in Sources */,
D5C7822F2BF88755001EBB3A /* MenuTaskView.swift in Sources */,
027EF9F22B0D804C0079B825 /* WebView.swift in Sources */, 027EF9F22B0D804C0079B825 /* WebView.swift in Sources */,
020B984B2AD915810029DE4C /* QRReadView.swift in Sources */, 020B984B2AD915810029DE4C /* QRReadView.swift in Sources */,
02A1DE332AFB654A005BCF55 /* CustomCornerRadius.swift in Sources */, 02A1DE332AFB654A005BCF55 /* CustomCornerRadius.swift in Sources */,
...@@ -1050,6 +1088,7 @@ ...@@ -1050,6 +1088,7 @@
025C27FE2B0206D700BADC49 /* PDFDownloadManager.swift in Sources */, 025C27FE2B0206D700BADC49 /* PDFDownloadManager.swift in Sources */,
D59908CA2B1AC381000E13DD /* GetPushHistory.swift in Sources */, D59908CA2B1AC381000E13DD /* GetPushHistory.swift in Sources */,
D54D174B2B35137A00A0EAA5 /* LocalWebView.swift in Sources */, D54D174B2B35137A00A0EAA5 /* LocalWebView.swift in Sources */,
D539F3302C1809790088E609 /* NgaTask.swift in Sources */,
D5FCEF572B4789A8009A81D0 /* ResAckMessage.swift in Sources */, D5FCEF572B4789A8009A81D0 /* ResAckMessage.swift in Sources */,
025C27FC2AFE191A00BADC49 /* MenuManualView.swift in Sources */, 025C27FC2AFE191A00BADC49 /* MenuManualView.swift in Sources */,
D58E1F502B142A260092D8FE /* EcaArea.swift in Sources */, D58E1F502B142A260092D8FE /* EcaArea.swift in Sources */,
...@@ -1064,6 +1103,8 @@ ...@@ -1064,6 +1103,8 @@
D5E03A672B04484D00D65FCE /* SessionTaskList.swift in Sources */, D5E03A672B04484D00D65FCE /* SessionTaskList.swift in Sources */,
020B986E2ADD3E8D0029DE4C /* DateTextLib.swift in Sources */, 020B986E2ADD3E8D0029DE4C /* DateTextLib.swift in Sources */,
D5258C9D2B03507A00365276 /* ResMonitoringRoute.swift in Sources */, D5258C9D2B03507A00365276 /* ResMonitoringRoute.swift in Sources */,
D5C782462BFB55F0001EBB3A /* DeleteNgaArea.swift in Sources */,
D5C782492BFC2DA2001EBB3A /* NgaSettingView.swift in Sources */,
020B98672ADD15050029DE4C /* MenuView.swift in Sources */, 020B98672ADD15050029DE4C /* MenuView.swift in Sources */,
020B98572AD924F50029DE4C /* CameraPreview.swift in Sources */, 020B98572AD924F50029DE4C /* CameraPreview.swift in Sources */,
D5CB6FA12B023F7F00EC2010 /* EcaTask.swift in Sources */, D5CB6FA12B023F7F00EC2010 /* EcaTask.swift in Sources */,
...@@ -1258,7 +1299,7 @@ ...@@ -1258,7 +1299,7 @@
CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements; CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 22; CURRENT_PROJECT_VERSION = 25;
DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\"";
DEVELOPMENT_TEAM = D2DC7QNNJ8; DEVELOPMENT_TEAM = D2DC7QNNJ8;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
...@@ -1282,7 +1323,7 @@ ...@@ -1282,7 +1323,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.2; MARKETING_VERSION = 1.0.3;
OTHER_SWIFT_FLAGS = "-D CANARY -D COCOAPODS"; OTHER_SWIFT_FLAGS = "-D CANARY -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.canary; PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.canary;
PRODUCT_NAME = "Sail Assist"; PRODUCT_NAME = "Sail Assist";
...@@ -1304,7 +1345,7 @@ ...@@ -1304,7 +1345,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements; CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 22; CURRENT_PROJECT_VERSION = 25;
DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\"";
DEVELOPMENT_TEAM = D2DC7QNNJ8; DEVELOPMENT_TEAM = D2DC7QNNJ8;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
...@@ -1325,7 +1366,7 @@ ...@@ -1325,7 +1366,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.2; MARKETING_VERSION = 1.0.3;
OTHER_SWIFT_FLAGS = "-D COCOAPODS"; OTHER_SWIFT_FLAGS = "-D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist; PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist;
PRODUCT_NAME = "Sail Assist"; PRODUCT_NAME = "Sail Assist";
...@@ -1488,7 +1529,7 @@ ...@@ -1488,7 +1529,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements; CODE_SIGN_ENTITLEMENTS = Sailassist/Sailassist.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 22; CURRENT_PROJECT_VERSION = 25;
DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Sailassist/Preview Content\"";
DEVELOPMENT_TEAM = D2DC7QNNJ8; DEVELOPMENT_TEAM = D2DC7QNNJ8;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
...@@ -1512,7 +1553,7 @@ ...@@ -1512,7 +1553,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0.2; MARKETING_VERSION = 1.0.3;
OTHER_SWIFT_FLAGS = "-D QC -D COCOAPODS"; OTHER_SWIFT_FLAGS = "-D QC -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.qc; PRODUCT_BUNDLE_IDENTIFIER = com.jrc.sailassist.qc;
PRODUCT_NAME = "Sail Assist"; PRODUCT_NAME = "Sail Assist";
......
{
"images" : [
{
"filename" : "plus.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "areaPoint.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "target.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -12,11 +12,13 @@ struct WarnRecord { ...@@ -12,11 +12,13 @@ struct WarnRecord {
var body: String var body: String
} }
enum SwitchingEca { enum SwitchingAlert {
case Finish case Finish
case Start case Start
case Notice case Notice
case NgaPassing
init() { init() {
self = .Notice self = .Notice
} }
...@@ -26,14 +28,21 @@ class AlertDB { ...@@ -26,14 +28,21 @@ class AlertDB {
// シングルトン宣言 // シングルトン宣言
static let OnlyOne = AlertDB() static let OnlyOne = AlertDB()
private var alertEca : [SwitchingEca: WarnRecord] = [ private var alertEca : [SwitchingAlert: WarnRecord] = [
SwitchingEca.Finish: WarnRecord(title: NSLocalizedString("No Fuel Switching Finished", comment: ""), body: NSLocalizedString("Arrived at switching finished point.", comment: "")) SwitchingAlert.Finish: WarnRecord(title: String("No Fuel Switching Finished"), body: String("Arrived at switching finished point.")),
, SwitchingEca.Start: WarnRecord(title: NSLocalizedString("Eca Start", comment: ""), body: NSLocalizedString("Arrived at switching start point.", comment: "")) SwitchingAlert.Start: WarnRecord(title: NSLocalizedString("Eca Start", comment: ""), body: NSLocalizedString("Arrived at switching start point.", comment: "")),
, SwitchingEca.Notice: WarnRecord(title: NSLocalizedString("Eca Notice", comment: ""), body: NSLocalizedString("Arrived at advance notice point.", comment: "")) SwitchingAlert.Notice: WarnRecord(title: NSLocalizedString("Eca Notice", comment: ""), body: NSLocalizedString("Arrived at advance notice point.", comment: "")),
SwitchingAlert.NgaPassing: WarnRecord(title: String("Nga Notice "), body: String("Nga Passing."))
] ]
//Eca通知 //Eca通知
func GetAlertEcaPoint(point : SwitchingEca) -> WarnRecord { func GetAlertEcaPoint(point : SwitchingAlert) -> WarnRecord {
return alertEca[point]!
}
//Nga通知
func GetAlertNgaPoint(point : SwitchingAlert) -> WarnRecord {
return alertEca[point]! return alertEca[point]!
} }
} }
...@@ -12,6 +12,7 @@ struct PushNotificationTypes { ...@@ -12,6 +12,7 @@ struct PushNotificationTypes {
enum SendType: Int32{ enum SendType: Int32{
case Error = -1 case Error = -1
case Eca = 0 // Eca case Eca = 0 // Eca
case Nga = 1 //Nga
init(){ init(){
self = .Error self = .Error
...@@ -29,5 +30,6 @@ struct PushNotificationTypes { ...@@ -29,5 +30,6 @@ struct PushNotificationTypes {
enum LocalPushIdentifier: String{ enum LocalPushIdentifier: String{
case Reserve = "Reserve" // 予約(初期設定) case Reserve = "Reserve" // 予約(初期設定)
case EcaSwitching = "Eca" // Eca case EcaSwitching = "Eca" // Eca
case NgaAlert = "Nga" // Nga
} }
} }
...@@ -47,7 +47,7 @@ class EcaArea { ...@@ -47,7 +47,7 @@ class EcaArea {
private func tableInit() { private func tableInit() {
for data in ecaDataTable { for data in ecaDataTable {
if !ecaData.ecaArea.keys.contains(data.areaId) { if !ecaData.ecaArea.keys.contains(data.areaId) {
var reg = RegisteredEca(id: data.areaId, ecaName: data.name)! var reg = RegisteredEca(id: data.areaId, areaName: data.name)!
reg.color = "0xFF0000" //ライン色(ARGB) reg.color = "0xFF0000" //ライン色(ARGB)
reg.centerPosition = data.centerPosition reg.centerPosition = data.centerPosition
reg.zoomLevel = data.zoomLevel reg.zoomLevel = data.zoomLevel
......
...@@ -20,7 +20,7 @@ class EcaTask { ...@@ -20,7 +20,7 @@ class EcaTask {
/** /**
* Eca通知 * Eca通知
*/ */
private func notificationEca(point: SwitchingEca) { private func notificationEca(point: SwitchingAlert) {
let alertDB = AlertDB.OnlyOne let alertDB = AlertDB.OnlyOne
var wernrec = WarnRecord(title:"Eca", body:"") var wernrec = WarnRecord(title:"Eca", body:"")
...@@ -75,7 +75,7 @@ class EcaTask { ...@@ -75,7 +75,7 @@ class EcaTask {
// } // }
if eca.swFinish >= Float(distance) && 0.0 < Float(distance) && SharingData.my.ecaStatus != EcaState.finishPass{ if eca.swFinish >= Float(distance) && 0.0 < Float(distance) && SharingData.my.ecaStatus != EcaState.finishPass{
// notificationEca(point: SwitchingEca.Finish) // notificationEca(point: SwitchingAlert.Finish)
SharingData.eca.isShowEcaAlert = true SharingData.eca.isShowEcaAlert = true
SharingData.my.ecaStatus = EcaState.finishPass SharingData.my.ecaStatus = EcaState.finishPass
...@@ -84,7 +84,7 @@ class EcaTask { ...@@ -84,7 +84,7 @@ class EcaTask {
} }
if eca.swStart >= Float(distance) && eca.swFinish < Float(distance) && SharingData.my.ecaStatus != EcaState.startPass{ if eca.swStart >= Float(distance) && eca.swFinish < Float(distance) && SharingData.my.ecaStatus != EcaState.startPass{
notificationEca(point: SwitchingEca.Start) notificationEca(point: SwitchingAlert.Start)
SharingData.eca.isShowEcaAlert = true SharingData.eca.isShowEcaAlert = true
SharingData.my.ecaStatus = EcaState.startPass SharingData.my.ecaStatus = EcaState.startPass
...@@ -93,7 +93,7 @@ class EcaTask { ...@@ -93,7 +93,7 @@ class EcaTask {
} }
if eca.swNotice >= Float(distance) && eca.swStart < Float(distance) && SharingData.my.ecaStatus != EcaState.noticePass{ if eca.swNotice >= Float(distance) && eca.swStart < Float(distance) && SharingData.my.ecaStatus != EcaState.noticePass{
notificationEca(point: SwitchingEca.Notice) notificationEca(point: SwitchingAlert.Notice)
SharingData.eca.isShowEcaAlert = true SharingData.eca.isShowEcaAlert = true
SharingData.my.ecaStatus = EcaState.noticePass SharingData.my.ecaStatus = EcaState.noticePass
......
...@@ -44,8 +44,8 @@ struct RegisteredEca { ...@@ -44,8 +44,8 @@ struct RegisteredEca {
var zoomLevel: CGFloat = 11.0 var zoomLevel: CGFloat = 11.0
var points: [CLLocationCoordinate2D] = [] var points: [CLLocationCoordinate2D] = []
init?(id: Int, ecaName: String ) { init?(id: Int, areaName: String ) {
self.areaId = id self.areaId = id
self.name = ecaName self.name = areaName
} }
} }
...@@ -16,6 +16,7 @@ enum HttpRequestType : String { ...@@ -16,6 +16,7 @@ enum HttpRequestType : String {
// case CookiePolicy = "https://ssv-canary-web.azurewebsites.net/cookiepolicy" // case CookiePolicy = "https://ssv-canary-web.azurewebsites.net/cookiepolicy"
// case PrivacyPolicy = "https://ssv-canary-web.azurewebsites.net/inapp?" //+バージョン番号 // case PrivacyPolicy = "https://ssv-canary-web.azurewebsites.net/inapp?" //+バージョン番号
case TaskList = "https://ssv-canary-web.azurewebsites.net/api/sailassist/tasklist/XXXXX" case TaskList = "https://ssv-canary-web.azurewebsites.net/api/sailassist/tasklist/XXXXX"
case NgaList = "https://ssv-canary-web.azurewebsites.net/api/sailassist/nogoarea/XXXXX"
case EcaArea = "https://ssv-canary-web.azurewebsites.net/api/sailassist/ecaarea/XXXXX" case EcaArea = "https://ssv-canary-web.azurewebsites.net/api/sailassist/ecaarea/XXXXX"
case ShipStatus = "https://ssv-canary-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX" case ShipStatus = "https://ssv-canary-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX"
case ShipMonitoringRoute = "https://ssv-canary-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX" case ShipMonitoringRoute = "https://ssv-canary-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX"
...@@ -42,6 +43,7 @@ enum HttpRequestType : String { ...@@ -42,6 +43,7 @@ enum HttpRequestType : String {
// case CookiePolicy = "https://ssv-qc-web.azurewebsites.net/cookiepolicy" // case CookiePolicy = "https://ssv-qc-web.azurewebsites.net/cookiepolicy"
// case PrivacyPolicy = "https://ssv-qc-web.azurewebsites.net/inapp?" //+バージョン番号 // case PrivacyPolicy = "https://ssv-qc-web.azurewebsites.net/inapp?" //+バージョン番号
case TaskList = "https://ssv-qc-web.azurewebsites.net/api/sailassist/tasklist/XXXXX" case TaskList = "https://ssv-qc-web.azurewebsites.net/api/sailassist/tasklist/XXXXX"
case NgaList = "https://ssv-qc-web.azurewebsites.net/api/sailassist/nogoarea/XXXXX"
case EcaArea = "https://ssv-qc-web.azurewebsites.net/api/sailassist/ecaarea/XXXXX" case EcaArea = "https://ssv-qc-web.azurewebsites.net/api/sailassist/ecaarea/XXXXX"
case ShipStatus = "https://ssv-qc-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX" case ShipStatus = "https://ssv-qc-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX"
case ShipMonitoringRoute = "https://ssv-qc-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX" case ShipMonitoringRoute = "https://ssv-qc-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX"
...@@ -69,6 +71,7 @@ enum HttpRequestType : String { ...@@ -69,6 +71,7 @@ enum HttpRequestType : String {
// case CookiePolicy = "https://ssv.jmarinecloud.com/cookiepolicy" // case CookiePolicy = "https://ssv.jmarinecloud.com/cookiepolicy"
// case PrivacyPolicy = "https://ssv.jmarinecloud.com/inapp?" //+バージョン番号 // case PrivacyPolicy = "https://ssv.jmarinecloud.com/inapp?" //+バージョン番号
case TaskList = "https://ssv.jmarinecloud.com/api/sailassist/tasklist/XXXXX" case TaskList = "https://ssv.jmarinecloud.com/api/sailassist/tasklist/XXXXX"
case NgaList = "https://ssv.jmarinecloud.com/api/sailassist/nogoarea/XXXXX"
case EcaArea = "https://ssv.jmarinecloud.com/api/sailassist/ecaarea/XXXXX" case EcaArea = "https://ssv.jmarinecloud.com/api/sailassist/ecaarea/XXXXX"
case ShipStatus = "https://ssv.jmarinecloud.com/api/sailassist/shipstatus/XXXXX" case ShipStatus = "https://ssv.jmarinecloud.com/api/sailassist/shipstatus/XXXXX"
case ShipMonitoringRoute = "https://ssv.jmarinecloud.com/api/sailassist/shipmonitoringroute/XXXXX" case ShipMonitoringRoute = "https://ssv.jmarinecloud.com/api/sailassist/shipmonitoringroute/XXXXX"
......
//
// ReqNgaList.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/06/14.
//
import Foundation
struct ReqNgaList : Codable {
var id: String = ""
var lock: Bool = false
var enabled: Bool = false
var geometry: [points] = []
init(Id: String) {
self.id = Id
}
}
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
import Foundation import Foundation
struct ReqTaskList : Codable { struct ReqTaskList : Codable {
// var id: String = ""
var areaId: Int = 0 var areaId: Int = 0
var taskName: String = "" var taskName: String = ""
// var name: String = ""
var noticeRange: Float = 0.0 var noticeRange: Float = 0.0
var startRange: Float = 0.0 var startRange: Float = 0.0
var finishRange: Float = 0.0 var finishRange: Float = 0.0
......
...@@ -10,8 +10,18 @@ import Foundation ...@@ -10,8 +10,18 @@ import Foundation
import CoreLocation import CoreLocation
// import Mapbox // import Mapbox
struct PointC {
var x: Int
var y: Int
}
class LocationCalculation{ class LocationCalculation{
static let nm = 1852.0 // 国際海里 1852.0[m] static let nm = 1852.0 // 国際海里 1852.0[m]
static let DI_BIAS = 10000000.0 //計算精度を1/100000°(暫定的、多分今後のGPS測位精度から推測しても十分なはず
static let ACCY_ROOT = 0.0000001
static let ACCY_COORD = 0.001
static let ACCY_RAD = 0.000001
static let ACCY_DEG = 0.0001
/** /**
* NMをkmに変換 * NMをkmに変換
...@@ -140,7 +150,6 @@ class LocationCalculation{ ...@@ -140,7 +150,6 @@ class LocationCalculation{
} }
} }
/// 起点から指定の距離方位分移動した地点の緯度経度 /// 起点から指定の距離方位分移動した地点の緯度経度
/// - Parameters: /// - Parameters:
/// - startPointLat: 起点緯度 /// - startPointLat: 起点緯度
...@@ -190,13 +199,16 @@ class LocationCalculation{ ...@@ -190,13 +199,16 @@ class LocationCalculation{
return CLLocationCoordinate2D(latitude: lat, longitude: lon) return CLLocationCoordinate2D(latitude: lat, longitude: lon)
} }
static func halfPoint(posA:CLLocationCoordinate2D, posB:CLLocationCoordinate2D) -> CLLocationCoordinate2D {
return CLLocationCoordinate2D(latitude: ((posA.latitude + posB.latitude) / 2), longitude: ((posA.longitude + posB.longitude) / 2))
}
/// Plygonの中心の位置 /// Plygonの中心の位置
/// - Parameters: /// - Parameters:
/// - positions: 地点配列 /// - positions: 地点配列
/// - Returns: /// - Returns:
/// Polygonの中間緯度経度 /// Polygonの中間緯度経度
static func CenterPoint(positions : [CLLocationCoordinate2D]) -> CLLocationCoordinate2D { static func CenterPoint(positions : [CLLocationCoordinate2D]) -> CLLocationCoordinate2D {
var latMax : Double = 0 var latMax : Double = 0
var latMin : Double = 360 var latMin : Double = 360
var lonMax : Double = 0 var lonMax : Double = 0
...@@ -221,6 +233,35 @@ class LocationCalculation{ ...@@ -221,6 +233,35 @@ class LocationCalculation{
return CLLocationCoordinate2D(latitude: lat, longitude: lon) return CLLocationCoordinate2D(latitude: lat, longitude: lon)
} }
static func CenterPoint2(positions : [CLLocationCoordinate2D]) -> CLLocationCoordinate2D {
var Max: CLLocationCoordinate2D = .init(latitude: 0, longitude: 0)
var Min: CLLocationCoordinate2D = .init(latitude: 0, longitude: 0)
Max = positions[0]
Min = positions[0]
for position in positions {
if fabs(Max.latitude) < fabs(position.latitude) {
Max.latitude = position.latitude
}
if fabs(Min.latitude) > fabs(position.latitude) {
Min.latitude = position.latitude
}
if fabs(Max.longitude) < fabs(position.longitude) {
Max.longitude = position.longitude
}
if fabs(Min.longitude) > fabs(position.longitude) {
Min.longitude = position.longitude
}
}
var ret = CLLocationCoordinate2D()
ret.latitude = (Max.latitude + Min.latitude) / 2
ret.longitude = (Max.longitude + Min.longitude) / 2
return ret
}
/// 緯度を数値から文字列に変換 /// 緯度を数値から文字列に変換
/// - Parameters: /// - Parameters:
/// - lat: 緯度数値 /// - lat: 緯度数値
...@@ -247,6 +288,8 @@ class LocationCalculation{ ...@@ -247,6 +288,8 @@ class LocationCalculation{
return "\(latDeg)°\(String(format:"%06.3f", latMin))\(latNS)" return "\(latDeg)°\(String(format:"%06.3f", latMin))\(latNS)"
} }
/// 経度を数値から文字列に変換 /// 経度を数値から文字列に変換
/// - Parameters: /// - Parameters:
/// - lon: 経度数値 /// - lon: 経度数値
...@@ -273,6 +316,47 @@ class LocationCalculation{ ...@@ -273,6 +316,47 @@ class LocationCalculation{
return "\(lonDeg)°\(String(format:"%06.3f", lonMin))\(lonEW)" return "\(lonDeg)°\(String(format:"%06.3f", lonMin))\(lonEW)"
} }
/**
* 緯度経度を数値から文字列に変換
*/
static func locationDegtoString(location: CLLocationCoordinate2D) -> String {
let latNS : String
if (location.latitude >= 0){
latNS = "N"
} else {
latNS = "S"
}
let latNum : CLLocationDegrees
if (location.latitude >= 0) {
latNum = location.latitude
}else{
latNum = -location.latitude
}
let latDeg = Int32(latNum)
let latMin = (latNum - CLLocationDegrees(latDeg)) * 60.0
let lonEW : String
if (location.longitude >= 0){
lonEW = "E"
}else{
lonEW = "W"
}
let lonNum : CLLocationDegrees
if (location.longitude >= 0){
lonNum = location.longitude
} else {
lonNum = -location.longitude
}
let lonDeg = Int32(lonNum)
let lonMin = (lonNum - CLLocationDegrees(lonDeg)) * 60.0
return "\(String(format:"%3d", latDeg))°\(String(format:"%06.3f", latMin))\(latNS)\n\(String(format:"%03d", lonDeg))°\(String(format:"%06.3f", lonMin))\(lonEW)"
}
/** /**
* 緯度の文字列を数値に変換 * 緯度の文字列を数値に変換
* NXX°XX.XX * NXX°XX.XX
...@@ -306,7 +390,6 @@ class LocationCalculation{ ...@@ -306,7 +390,6 @@ class LocationCalculation{
}else{ }else{
return nil return nil
} }
} }
/** /**
...@@ -344,6 +427,114 @@ class LocationCalculation{ ...@@ -344,6 +427,114 @@ class LocationCalculation{
} }
} }
/// 緯度の数値を分解
/// - Parameters:
/// - lat: 緯度数値
/// - Returns
/// 分解した数値
static func latDegtoInt(lat: CLLocationDegrees) -> [Int] {
var disLat : [Int] = []
if (lat >= 0){
disLat.append(0) //N
} else {
disLat.append(1) //S
}
let latNum : Double
if (lat >= 0) {
latNum = lat
}else{
latNum = -lat
}
let latDeg = Int(latNum)
let latMin = (latNum - Double(latDeg)) * 60.0
let latM = Int(latMin)
let latL = Int((latMin - Double(latM)) * 1000.0)
disLat.append(latDeg)
disLat.append(latM)
disLat.append(latL)
return disLat
}
/// 経度の数値を分解
/// - Parameters:
/// - lon: 経度数値
/// - Returns
/// 分解した数値
static func lonDegtoInt(lon: CLLocationDegrees) -> [Int] {
var disLat : [Int] = []
if (lon >= 0){
disLat.append(0) //E
}else{
disLat.append(1) //W
}
let lonNum : Double
if (lon >= 0){
lonNum = lon
} else {
lonNum = -lon
}
let lonDeg = Int(lonNum)
let lonMin = (lonNum - Double(lonDeg)) * 60.0
let lonM = Int(lonMin)
let lonL = Int((lonMin - Double(lonM)) * 1000.0)
disLat.append(lonDeg)
disLat.append(lonM)
disLat.append(lonL)
return disLat
}
/**
* 緯度の配列を数値に変換
* NXX°XX.XX
*/
static func latInttoDouble(lat: [Int]) -> CLLocationDegrees? {
if lat.count != 4 {
return nil
}
var direction : CLLocationDegrees
if lat[0] == 0 { //N
direction = 1.0
} else {
direction = -1.0
}
let deg0 : CLLocationDegrees = CLLocationDegrees(lat[1])
let deg1 : CLLocationDegrees = CLLocationDegrees(lat[2])
let min1 : CLLocationDegrees = CLLocationDegrees(lat[3])
let decimal = (deg1 + min1 / 1000) / 60.0
return ((deg0 + decimal) * direction)
}
/**
* 経度の配列を数値に変換
* EXXX°XX.XX
*/
static func lonInttoDouble(lon: [Int]) -> CLLocationDegrees? {
if lon.count != 4 {
return nil
}
var direction : CLLocationDegrees
if lon[0] == 0 { //E
direction = 1.0
} else {
direction = -1.0
}
let deg0 : CLLocationDegrees = CLLocationDegrees(lon[1])
let deg1 : CLLocationDegrees = CLLocationDegrees(lon[2])
let min1 : CLLocationDegrees = CLLocationDegrees(lon[3])
let decimal = (deg1 + min1 / 1000) / 60.0
return ((deg0 + decimal) * direction)
}
///時計回りか ///時計回りか
///return: 1 -> 時計回り ///return: 1 -> 時計回り
/// -1 -> 反時計回り /// -1 -> 反時計回り
...@@ -403,10 +594,10 @@ class LocationCalculation{ ...@@ -403,10 +594,10 @@ class LocationCalculation{
static let errorRange = 0.00001 //誤差範囲 static let errorRange = 0.00001 //誤差範囲
struct AreaLatLon { struct AreaLatLon {
var NorthLat: Double = 0.0 var NorthLat: CLLocationDegrees = 0.0
var SouthLat: Double = 0.0 var SouthLat: CLLocationDegrees = 0.0
var EastLon: Double = 0.0 var EastLon: CLLocationDegrees = 0.0
var WestLon: Double = 0.0 var WestLon: CLLocationDegrees = 0.0
} }
/** /**
...@@ -561,7 +752,7 @@ class LocationCalculation{ ...@@ -561,7 +752,7 @@ class LocationCalculation{
} }
} }
if lUpperCnt % 2 == 1 && lLowerCnt % 2 == 1{ if lUpperCnt % 2 == 1 && lLowerCnt % 2 == 1 {
return true return true
} else { } else {
return false return false
...@@ -1280,6 +1471,385 @@ class LocationCalculation{ ...@@ -1280,6 +1471,385 @@ class LocationCalculation{
return deg return deg
} }
/**
* ポイントがライン上にあるか
*
* build/src/EDrawChart/ECdgeometry.cpp ECdIsPointOnLine移植
*/
static func eCdIsPointOnLine(
pt: CLLocationCoordinate2D,
ptL: CLLocationCoordinate2D,
ptR: CLLocationCoordinate2D
) -> Bool {
var checkN = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
checkN.latitude = ptL.latitude - pt.latitude
checkN.longitude = ptL.longitude - pt.longitude
if checkN.latitude == 0 && checkN.longitude == 0 {
return true
}
var zero = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
zero.latitude = ptR.latitude - pt.latitude
zero.longitude = ptR.longitude - pt.longitude
if zero.latitude == 0 && zero.longitude == 0 {
return true
}
let inside = zero.latitude * checkN.latitude + zero.longitude * checkN.longitude
let outside = zero.latitude * checkN.longitude - checkN.latitude * zero.longitude
if fabs(outside) <= ACCY_ROOT {
if fabs(inside) <= ACCY_ROOT {
return true // 内積、外積が0ということは、点がポリゴンの頂点のどれかと一致しているということ
}
if inside < 0.0 {
return true // 内積が0ということは、点がポリゴンの線上にあるということ
}
}
return false
}
/**
* 自己交差チェック(32ビット正規化座標用)
*
* build/src/Chart/Stranding/EWc_Inner.cpp移植
*/
static func chkSelfIntersection(
wcPos: Array<CLLocationCoordinate2D>
) -> Bool {
let positionNum = wcPos.count
var point1: Array<CLLocationCoordinate2D> = [CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0), CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)]
var point2: Array<CLLocationCoordinate2D> = [CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0), CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)]
var idx1: Array<Int> = [0, 0]
var idx2: Array<Int> = [0, 0]
var bIntersect = false
for i in 0 ..< positionNum - 1 {
point1[0] = wcPos[i]
point1[1] = wcPos[i + 1]
if point1[0] == point1[1] {
continue
}
idx1[0] = i
idx1[1] = i + 1
for j in i + 1 ..< positionNum - 1 {
bIntersect = false
point2[0] = wcPos[j]
point2[1] = wcPos[j + 1]
if point2[0] == point2[1] {
continue
}
idx2[0] = j
idx2[1] = j + 1
if min(point1[0].longitude, point1[1].longitude) > max(point2[0].longitude, point2[1].longitude) {
continue
}
if max(point1[0].longitude, point1[1].longitude) < min(point2[0].longitude, point2[1].longitude) {
continue
}
if min(point1[0].latitude, point1[1].latitude) > max(point2[0].latitude, point2[1].latitude) {
continue
}
if max(point1[0].latitude, point1[1].latitude) < min(point2[0].latitude, point2[1].latitude) {
continue
}
let ret = eCdInterPointLL(pSp: point1, pEp: point2)
if ret.crossInf == 0 {
bIntersect = true // 交点あり
} else if ret.crossInf == 1 {
// 接線(頂点と頂点の接触、辺と頂点の接触)
if !(point1[1] == point2[0]) && (i + 1 == j) {
if !(i == 0 && ((j + 1) == (positionNum - 1)) && (point1[0] == point2[1])) {
bIntersect = true
}
}
} else if ret.crossInf == -2 {
// 平行
if point1[0].longitude != point1[1].longitude && point2[0].longitude != point2[1].longitude {
// 線分2の座標が線分1上に有るか調べる
var targetPt: CLLocationCoordinate2D
var ptR: CLLocationCoordinate2D
var ptL: CLLocationCoordinate2D
let minX = min(point1[0].longitude, point1[1].longitude)
let maxX = max(point1[0].longitude, point1[1].longitude)
if minX < point2[0].longitude && maxX > point2[0].longitude {
targetPt = point2[0]
} else {
targetPt = point2[1]
}
if point1[0].longitude < point1[1].longitude {
ptL = point1[0]
ptR = point1[1]
} else {
ptL = point1[1]
ptR = point1[0]
}
let ret = eCdIsPointOnLine(pt: targetPt, ptL: ptL, ptR: ptR)
if true == ret {
if (min(point1[0].longitude, point1[1].longitude) <= min(point2[0].longitude, point2[1].longitude) && max(point2[0].longitude, point2[1].longitude) <= max(point1[0].longitude, point1[1].longitude))
|| (min(point2[0].longitude, point2[1].longitude) <= min(point1[0].longitude, point1[1].longitude) && max(point1[0].longitude, point1[1].longitude) <= max(point2[0].longitude, point2[1].longitude)) {
bIntersect = true
} else if !((point1[1] == point2[0]) && (i + 1 == j)) {
if !((i == 0) && ((j + 1) == (positionNum - 1)) && (point1[0] == point2[1])) {
bIntersect = true
}
}
}
} else if point1[0].longitude == point2[0].longitude {
// 縦一線の場合
if point1[1].latitude == point2[1].latitude {
bIntersect = true
} else if (min(point1[0].latitude, point1[1].latitude) < point2[1].latitude && max(point1[0].latitude, point1[1].latitude) > point2[1].latitude)
&& (min(point2[0].latitude, point2[1].latitude) < point1[1].latitude && max(point2[0].latitude, point2[1].latitude) > point1[1].latitude) {
bIntersect = true
} else if (min(point1[0].latitude, point1[1].latitude) < point2[0].latitude && max(point1[0].latitude, point1[1].latitude) > point2[0].latitude)
&& (min(point2[0].latitude, point2[1].latitude) < point1[0].latitude && max(point2[0].latitude, point2[1].latitude) > point1[0].latitude) {
bIntersect = true
} else if min(point1[0].latitude, point1[1].latitude) < point2[1].latitude && max(point1[0].latitude, point1[1].latitude) > point2[1].latitude {
bIntersect = true
} else if min(point2[0].latitude, point2[1].latitude) < point1[1].latitude && max(point2[0].latitude, point2[1].latitude) > point1[1].latitude {
bIntersect = true
}
}
}
// 自己交差している
if true == bIntersect {
return true
}
}
}
return false
}
/**
* 2線分の交点を計算
* 0:交点有り 1:接線 -1:線分が存在しない
* -2:二線分が並行し交点がない
* -3:線分外で交点あり
*
* src/EDrawChart/ECdGeometry.cpp
*/
static func eCdInterPointLL(
pSp: Array<CLLocationCoordinate2D>,
pEp: Array<CLLocationCoordinate2D>
) -> (crossInf: Int, cross: CLLocationCoordinate2D) {
var resp: Int = 0
var sd = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
var dd = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
var cross = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
sd.longitude = pSp[1].longitude - pSp[0].longitude
sd.latitude = pSp[1].latitude - pSp[0].latitude
dd.longitude = pEp[1].longitude - pEp[0].longitude
dd.latitude = pEp[1].latitude - pEp[0].latitude
let rsqs = sd.longitude * sd.longitude + sd.latitude * sd.latitude
let rsqe = dd.longitude * dd.longitude + dd.latitude * dd.latitude
//引数の適切性をチェック
if (rsqe < ACCY_ROOT) || (rsqs < ACCY_ROOT) {
//引数が不適切のため、計算中止
resp = -1
} else {
// 2線分の始点差ベクトルを求める
var bd = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
bd.longitude = pEp[0].longitude - pSp[0].longitude
bd.latitude = pEp[0].latitude - pSp[0].latitude
// 2線分の外積が0に近い時は平行となる
let det = dd.longitude * sd.latitude - dd.latitude * sd.longitude
if fabs(det) < ACCY_ROOT {
resp = -2;
} else {
// 始点差ベクトルとの外積から(外積比によって)パラメータを計算
let detinv = 1.0 / det
let s = (dd.longitude * bd.latitude - dd.latitude * bd.longitude) * detinv
let t = (sd.longitude * bd.latitude - sd.latitude * bd.longitude) * detinv
let ns = s
let nt = t
// パラメータから交点を計算
var l = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
l.longitude = pSp[0].longitude + sd.longitude * s
l.latitude = pSp[0].latitude + sd.latitude * s
cross = l
// 交点が2線分の外にある?
if (ns + ACCY_ROOT < 0.0) || (ns - ACCY_ROOT > 1.0) || (nt + ACCY_ROOT < 0.0) || (nt - ACCY_ROOT > 1.0) {
resp = -3;
} else if (fabs(ns) <= ACCY_ROOT) || (fabs(ns - 1.0) <= ACCY_ROOT) || (fabs(nt) <= ACCY_ROOT) || (fabs(nt - 1.0) <= ACCY_ROOT) {
resp = 1
// 接線判定になっても算出された交点が
// ・線分がなす矩形に内包されていない場合は線分外とする
// ・各線分の始点と終点に合致しない場合は交点ありとする
repeat {
var lSp: Array<PointC> = [PointC(x: 0, y:0), PointC(x: 0, y:0)]
var lEp: Array<PointC> = [PointC(x: 0, y:0), PointC(x: 0, y:0)]
var ptCross = PointC(x: 0, y: 0)
lSp[0].x = Int(pSp[0].longitude)
lSp[0].y = Int(pSp[0].latitude)
lSp[1].x = Int(pSp[1].longitude)
lSp[1].y = Int(pSp[1].latitude)
lEp[0].x = Int(pEp[0].longitude)
lEp[0].y = Int(pEp[0].latitude)
lEp[1].x = Int(pEp[1].longitude)
lEp[1].y = Int(pEp[1].latitude)
ptCross.x = (Int)((cross.longitude < 0) ? (cross.longitude - 0.5) : (cross.longitude + 0.5))
ptCross.y = (Int)((cross.latitude < 0) ? (cross.latitude - 0.5) : (cross.latitude + 0.5))
// 線分がなす矩形に内包されていない場合は線分外とする
if lSp[0].x < lSp[1].x {
if ptCross.x < lSp[0].x || lSp[1].x < ptCross.x {
resp = -3
break
}
} else {
if ptCross.x < lSp[1].x || lSp[0].x < ptCross.x {
resp = -3
break
}
}
if lEp[0].x < lEp[1].x {
if ptCross.x < lEp[0].x || lEp[1].x < ptCross.x {
resp = -3
break
}
} else {
if ptCross.x < lEp[1].x || lEp[0].x < ptCross.x {
resp = -3
break
}
}
if lSp[0].y < lSp[1].y {
if ptCross.y < lSp[0].y || lSp[1].y < ptCross.y {
resp = -3
break
}
} else {
if ptCross.y < lSp[1].y || lSp[0].y < ptCross.y {
resp = -3
break
}
}
if lEp[0].y < lEp[1].y {
if ptCross.y < lEp[0].y || lEp[1].y < ptCross.y {
resp = -3
break
}
} else {
if ptCross.y < lEp[1].y || lEp[0].y < ptCross.y {
resp = -3
break
}
}
// 各線分の始点と終点に合致しない場合は交点ありとする
if !((lSp[0].x == ptCross.x) && (lSp[0].y == ptCross.y)) &&
!((lSp[1].x == ptCross.x) && (lSp[1].y == ptCross.y)) &&
!((lEp[0].x == ptCross.x) && (lEp[0].y == ptCross.y)) &&
!((lEp[1].x == ptCross.x) && (lEp[1].y == ptCross.y)) {
resp = 0
break
}
} while false
} else {
resp = 0
// 交差判定になっても算出された交点が
// 線分がなす矩形に内包されていない場合は線分外とする
repeat {
var lSp: Array<PointC> = [PointC(x: 0, y:0), PointC(x: 0, y:0)]
var lEp: Array<PointC> = [PointC(x: 0, y:0), PointC(x: 0, y:0)]
var ptCross = PointC(x: 0, y: 0)
lSp[0].x = Int(pSp[0].longitude)
lSp[0].y = Int(pSp[0].latitude)
lSp[1].x = Int(pSp[1].longitude)
lSp[1].y = Int(pSp[1].latitude)
lEp[0].x = Int(pEp[0].longitude)
lEp[0].y = Int(pEp[0].latitude)
lEp[1].x = Int(pEp[1].longitude)
lEp[1].y = Int(pEp[1].latitude)
ptCross.x = (Int)((cross.longitude < 0) ? (cross.longitude - 0.5) : (cross.longitude + 0.5))
ptCross.y = (Int)((cross.latitude < 0) ? (cross.latitude - 0.5) : (cross.latitude + 0.5))
if lSp[0].x < lSp[1].x {
if ptCross.x < lSp[0].x || lSp[1].x < ptCross.x {
resp = -3
break
}
} else {
if ptCross.x < lSp[1].x || lSp[0].x < ptCross.x {
resp = -3
break
}
}
if lEp[0].x < lEp[1].x {
if ptCross.x < lEp[0].x || lEp[1].x < ptCross.x {
resp = -3
break
}
} else {
if ptCross.x < lEp[1].x || lEp[0].x < ptCross.x {
resp = -3
break
}
}
if lSp[0].y < lSp[1].y {
if ptCross.y < lSp[0].y || lSp[1].y < ptCross.y {
resp = -3
break
}
} else {
if ptCross.y < lSp[1].y || lSp[0].y < ptCross.y {
resp = -3
break
}
}
if lEp[0].y < lEp[1].y {
if ptCross.y < lEp[0].y || lEp[1].y < ptCross.y {
resp = -3
break
}
} else {
if ptCross.y < lEp[1].y || lEp[0].y < ptCross.y {
resp = -3
break
}
}
// 各線分の始点と終点に合致しない場合は交点ありとする
if ((lSp[0].x == ptCross.x) && (lSp[0].y == ptCross.y)) ||
((lSp[1].x == ptCross.x) && (lSp[1].y == ptCross.y)) ||
((lEp[0].x == ptCross.x) && (lEp[0].y == ptCross.y)) ||
((lEp[1].x == ptCross.x) && (lEp[1].y == ptCross.y)) {
resp = 1
break
}
} while false
}
}
}
return (resp, cross)
}
/** /**
* 等角航法での推測位置計算 * 等角航法での推測位置計算
* 等角航法で始点座標とその方位から任意の距離における位置座標を求める * 等角航法で始点座標とその方位から任意の距離における位置座標を求める
...@@ -1321,4 +1891,195 @@ class LocationCalculation{ ...@@ -1321,4 +1891,195 @@ class LocationCalculation{
return drPos return drPos
} }
/**
* 直線と直線の交点検索
*
* build/src/Chart/DecisionAlgorithm.cpp
* テストまだ
*/
static func checkCrossLine(
p1: CLLocationCoordinate2D,
p2: CLLocationCoordinate2D,
sp: CLLocationCoordinate2D,
ep: CLLocationCoordinate2D
) -> Int {
var Max = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
var Min = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
var crossp = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
//直線p1-p2(Y=AX+B)とsp-ep(Y=CX+D)の交点チェック
//同じ経度の垂直線
if ((p2.longitude == p1.longitude) && (p1.longitude == ep.longitude) && (ep.longitude == sp.longitude)) {
Max.latitude = p1.latitude < p2.latitude ? p1.latitude : p2.latitude
Min.latitude = p1.latitude > p2.latitude ? p1.latitude : p2.latitude
//開始点がp1-p2に含まれる場合
if ((sp.latitude >= Min.latitude) && (sp.latitude <= Max.latitude)) {
crossp.latitude = sp.latitude
crossp.longitude = sp.longitude
return 1
}
//終了点がp1-p2に含まれる場合
else if (ep.latitude >= Min.latitude) && (ep.latitude <= Max.latitude) {
crossp.latitude = ep.latitude
crossp.longitude = ep.longitude
return 1
}
Max.latitude = sp.latitude < ep.latitude ? sp.latitude : ep.latitude
Min.latitude = sp.latitude > ep.latitude ? sp.latitude : ep.latitude
//p1がsp-epに含まれる場合
if ((p1.latitude >= Min.latitude) && (p1.latitude <= Max.latitude)) {
crossp.latitude = p1.latitude
crossp.longitude = p1.longitude
return 1
}
//p2がsp-epに含まれる場合
if ((p2.latitude >= Min.latitude) && (p2.latitude <= Max.latitude)) {
crossp.latitude = p2.latitude
crossp.longitude = p2.longitude
return 1
}
return 0
}
//同じ緯度の水平線
if ((p2.latitude == p1.latitude) && (p1.latitude == ep.latitude) && (ep.latitude == sp.latitude)) {
Max.longitude = p1.longitude < p2.longitude ? p1.longitude : p2.longitude
Min.longitude = p1.longitude > p2.longitude ? p1.longitude : p2.longitude
//開始点がp1-p2に含まれる場合
if ((sp.longitude >= Min.longitude) && sp.longitude <= Max.longitude) {
crossp.latitude = sp.latitude
crossp.longitude = sp.longitude
return 1
}
//終了点がp1-p2に含まれる場合
if ((ep.longitude >= Min.longitude) && (ep.longitude <= Max.longitude)) {
crossp.latitude = ep.latitude
crossp.longitude = ep.longitude
return 1
}
Max.longitude = sp.longitude < ep.longitude ? sp.longitude : ep.longitude
Min.longitude = sp.longitude > ep.longitude ? sp.longitude : ep.longitude
//p1がsp-epに含まれる場合
if ((p1.longitude >= Min.longitude) && (p1.longitude <= Max.longitude)) {
crossp.latitude = p1.latitude
crossp.longitude = p1.longitude
return 1
}
//p2がwp-epに含まれる場合
if ((p2.longitude >= Min.longitude) && (p2.longitude <= Max.longitude)) {
crossp.latitude = p2.latitude
crossp.longitude = p2.longitude
return 1
}
return 0
}
//違う垂直線
if ((p2.longitude == p1.longitude) && (ep.longitude == sp.longitude)) {
return 0
}
//違う水平線
if ((p2.latitude == p1.latitude) && (ep.latitude == sp.latitude)) {
return 0
}
var a, b, c, d : Double
crossp.longitude = 400
if (p2.longitude == p1.longitude) {
//p1-p2だけ垂直線
crossp.longitude = p1.longitude
crossp.latitude = (ep.latitude - sp.latitude) / (ep.longitude - sp.longitude) * p1.longitude + (sp.latitude * ep.longitude - sp.longitude * ep.latitude) / (ep.longitude - sp.longitude)
} else if (ep.longitude == sp.longitude) {
//sp-epだけ垂直線
crossp.longitude = sp.longitude
crossp.latitude = (p2.latitude - p1.latitude) / (p2.longitude - p1.longitude) * sp.longitude + (p1.latitude * p2.longitude - p1.longitude * p2.latitude) / (p2.longitude - p1.longitude)
} else if (p2.latitude == p1.latitude) {
//p1-p2だけ水平線
crossp.latitude = p1.latitude
crossp.longitude = (p1.latitude * (ep.longitude - sp.longitude) - (sp.latitude * ep.longitude - sp.longitude * ep.latitude)) / (ep.latitude - sp.latitude)
} else if (sp.latitude == ep.latitude) {
//sp-epだけ水平線
crossp.latitude = sp.latitude
crossp.longitude = (sp.latitude * (p2.longitude - p1.longitude) - (p1.latitude * p2.longitude - p1.longitude * p2.latitude)) / (p2.latitude - p1.latitude)
} else if ((p2.latitude - p1.latitude) / (p2.longitude - p1.longitude) == (ep.latitude - sp.latitude) / (ep.longitude - sp.longitude)) {
//両方とも垂直線、平行線ではなく2本の線が平行である時
crossp.longitude = p1.longitude
crossp.latitude = (ep.latitude - sp.latitude) / (ep.longitude - sp.longitude) * p1.longitude + (sp.latitude * ep.longitude - sp.longitude * ep.latitude) / (ep.longitude - sp.longitude)
//p1がsp-ep上の点か?
if (crossp.latitude == p1.latitude) {
return 1
}
crossp.longitude = p2.longitude
crossp.latitude = (ep.latitude - sp.latitude) / (ep.longitude - sp.longitude) * p2.longitude + (sp.latitude * ep.longitude - sp.longitude * ep.latitude) / (ep.longitude - sp.longitude)
//p2がsp-ep上の点か?
if (crossp.latitude == p2.latitude) {
return 1
}
crossp.longitude = sp.longitude
crossp.latitude = (p2.latitude - p1.latitude) / (p2.longitude - p1.longitude) * sp.longitude + (p1.latitude * p2.longitude - p1.longitude * p2.latitude) / (p2.longitude - p1.longitude)
//spがp1-p2上の点か?
if (crossp.latitude == sp.latitude) {
return 1
}
crossp.longitude = ep.longitude
crossp.latitude = (p2.latitude - p1.latitude) / (p2.longitude - p1.longitude) * ep.longitude + (p1.latitude * p2.longitude - p1.longitude * p2.latitude) / (p2.longitude - p1.longitude)
//epがp1-p2上の点か?
if (crossp.latitude == ep.latitude) {
return 1
}
//それ以外--別の平行線
return 0
} else {
a = (p2.latitude - p1.latitude) / (p2.longitude - p1.longitude)
b = (p1.latitude * p2.longitude - p1.longitude * p2.latitude) / (p2.longitude - p1.longitude)
c = (ep.latitude - sp.latitude) / (ep.longitude - sp.longitude)
d = (sp.latitude * ep.longitude - sp.longitude * ep.latitude) / (ep.longitude - sp.longitude)
crossp.longitude = (d - b) / (a - c)
crossp.latitude = (c * b - a * d) / (c - a)
}
//@@@ 2000/10/13 交点がどの線分上に存在するか判定する部分は、交点そのものをDOUBLEで計算していることから
// その線分の性質に沿った判定をする必要がある。
// 例えば水平線と任意の傾きをもった線分が交差する場合その交点を計算式で求めてもY座標値は
// 水平線のY座標とは異なってしまうはず(論理的には正しくとも、倍精度計算の丸め誤差により
// 正確に一致はしない)よって計算結果の有効桁数を小数点以下6桁で計算する。
if (crossp.longitude != 400) {
var iMaxX, iMaxY, iMinX, iMinY, iCrosX, iCrosY: Int
//求めた交点が線分p1-p2, sp-ep上にあるか?
Min.longitude = p1.longitude < p2.longitude ? p1.longitude : p2.longitude
Max.longitude = p1.longitude > p2.longitude ? p1.longitude : p2.longitude
Min.latitude = p1.latitude < p2.latitude ? p1.latitude : p2.latitude
Max.latitude = p1.latitude > p2.latitude ? p1.latitude : p2.latitude
iMinX = Int(round(Min.longitude * DI_BIAS))
iMinY = Int(round(Min.latitude * DI_BIAS))
iMaxX = Int(round(Max.longitude * DI_BIAS))
iMaxY = Int(round(Max.latitude * DI_BIAS))
iCrosX = Int(round(crossp.longitude * DI_BIAS))
iCrosY = Int(round(crossp.latitude * DI_BIAS))
if ((iMinX <= iCrosX) && (iCrosX <= iMaxX) && (iMinY <= iCrosY) && (iCrosY <= iMaxY)) {
//領域内で交わる
Min.longitude = sp.longitude < ep.longitude ? sp.longitude : ep.longitude
Max.longitude = sp.longitude > ep.longitude ? sp.longitude : ep.longitude
Min.latitude = sp.latitude < ep.latitude ? sp.latitude : ep.latitude
Max.latitude = sp.latitude > ep.latitude ? sp.latitude : ep.latitude
iMinX = Int(round(Min.longitude * DI_BIAS))
iMinY = Int(round(Min.latitude * DI_BIAS))
iMaxX = Int(round(Max.longitude * DI_BIAS))
iMaxY = Int(round(Max.latitude * DI_BIAS))
if ((iMinX <= iCrosX) && (iCrosX <= iMaxX) && (iMinY <= iCrosY) && (iCrosY <= iMaxY)) {
//線分内で交わる
return 1
} else {
return 0
}
} else {
return 0
}
}
return 0
}
} }
...@@ -14,6 +14,7 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { ...@@ -14,6 +14,7 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
private let locationManager: CLLocationManager private let locationManager: CLLocationManager
let ecaTask = EcaTask() let ecaTask = EcaTask()
let ngaTask = NgaTask()
override init() { override init() {
let ecaArea = EcaArea() let ecaArea = EcaArea()
...@@ -84,6 +85,7 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { ...@@ -84,6 +85,7 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
if Preferences.LocationType == 0 { if Preferences.LocationType == 0 {
ecaTask.checkEca() ecaTask.checkEca()
ngaTask.checkNga()
} }
} }
...@@ -91,8 +93,9 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate { ...@@ -91,8 +93,9 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
if serverLocationInterval <= DateTextLib.Date2UnixTime(date: Date()) { if serverLocationInterval <= DateTextLib.Date2UnixTime(date: Date()) {
let eca = EcaTask() let eca = EcaTask()
eca.start() eca.start()
self.ecaTask.checkEca() self.ecaTask.checkEca()
self.ngaTask.checkNga()
serverLocationInterval = DateTextLib.Date2UnixTime(date: Date()) + Int64(TimerInterval) serverLocationInterval = DateTextLib.Date2UnixTime(date: Date()) + Int64(TimerInterval)
} }
} }
......
...@@ -221,6 +221,9 @@ struct LoginView: View { ...@@ -221,6 +221,9 @@ struct LoginView: View {
let ecaList = GetEcaList() let ecaList = GetEcaList()
ecaList.start() ecaList.start()
let ngaList = GetNgaList()
ngaList.start()
let pushHistory = GetPushHistory() let pushHistory = GetPushHistory()
pushHistory.start() pushHistory.start()
} }
......
...@@ -127,6 +127,9 @@ struct InputUserNameView: View { ...@@ -127,6 +127,9 @@ struct InputUserNameView: View {
let ecaList = GetEcaList() let ecaList = GetEcaList()
ecaList.start() ecaList.start()
let ngaList = GetNgaList()
ngaList.start()
let pushHistory = GetPushHistory() let pushHistory = GetPushHistory()
pushHistory.start() pushHistory.start()
} }
......
//
// LayerEnum.swift
// forShip
//
// Created by Mamoru Sugita on 2023/10/23.
//
import Foundation
enum LayerEnum: String{
case OwnShip
case EcaLine
case SwitchingLine
case SwLineLabel
case WayPoints
case WakeLines
case OneTimeEca
}
//
// MapInformation.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/06/12.
//
import SwiftUI
struct MapInformation: View {
@ObservedObject var ship = SharingData.location
@ObservedObject var ngaData = SharingData.nga
var body: some View {
VStack {
VStack {
Text(presentLocation())
.font(Font(UIFont.monospacedSystemFont(ofSize: 12, weight: .regular)))
.foregroundColor(Color.black)
.padding(5)
.background(Color.white.opacity(0.7))
.cornerRadius(3)
}
.padding(.top, 100)
.padding(.trailing, 200)
VStack {
ForEach(ngaData.ngaArea.map{ $0.1 }.filter{ $0.passingCnt > 0 }, id: \.name) { nga in
Text("Entering NGA \(nga.name)")
.font(FontStyle.EmphasisText.font)
.foregroundColor(Color.white)
.padding(5)
.background(Color.red.opacity(0.7))
.cornerRadius(3)
}
}
Spacer()
}
}
func presentLocation() -> String {
var location = " 00°00.000'N\n000°00.000'E"
if let shipPos = ship.location {
location = LocationCalculation.locationDegtoString(location: shipPos)
}
return location
}
}
#Preview {
MapInformation()
}
...@@ -10,8 +10,9 @@ import SwiftUI ...@@ -10,8 +10,9 @@ import SwiftUI
import MapboxMaps import MapboxMaps
import UIKit import UIKit
struct MapRepresentable: UIViewControllerRepresentable{ struct MapRepresentable: UIViewControllerRepresentable {
@ObservedObject var ecaData = SharingData.eca @ObservedObject var ecaData = SharingData.eca
@ObservedObject var ngaData = SharingData.nga
@ObservedObject var location = SharingData.location @ObservedObject var location = SharingData.location
@ObservedObject var map = SharingData.map @ObservedObject var map = SharingData.map
@ObservedObject var pushHistory = SharingData.pushHistory @ObservedObject var pushHistory = SharingData.pushHistory
...@@ -25,14 +26,14 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -25,14 +26,14 @@ struct MapRepresentable: UIViewControllerRepresentable{
//Viewが更新された場合に必要な処理を実装 //Viewが更新された場合に必要な処理を実装
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
let ecaArea = ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first let ecaArea = ecaData.ecaArea.map{ $0.1 }.filter{ $0.isRunning }.first
if let ecaArea = ecaArea{ if let ecaArea = ecaArea {
mapVC.updateEcaLine(line: ecaArea.points) mapVC.updateEcaLine(line: ecaArea.points)
} else { } else {
mapVC.removeEcaLine() mapVC.removeEcaLine()
} }
//ECA領域を画面中央に表示 //ECA領域を画面中央に表示
if let focusEcaAreaId = ecaData.focusEca, let focusEca = ecaData.ecaArea[focusEcaAreaId]{ if let focusEcaAreaId = ecaData.focusEca, let focusEca = ecaData.ecaArea[focusEcaAreaId] {
mapVC.updateCamera(location: focusEca.centerPosition, zoomlevel: focusEca.zoomLevel) mapVC.updateCamera(location: focusEca.centerPosition, zoomlevel: focusEca.zoomLevel)
mapVC.updateOneTimeEca(eca: focusEca.points) mapVC.updateOneTimeEca(eca: focusEca.points)
//10秒後削除 //10秒後削除
...@@ -41,8 +42,18 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -41,8 +42,18 @@ struct MapRepresentable: UIViewControllerRepresentable{
} }
} }
//NGA領域を画面中央に表示
if let AreaId = ngaData.focusNga, let uuid = NSUUID(uuidString: AreaId) {
if let focusNga = ngaData.ngaArea[uuid as UUID] {
if focusNga.points.count > 0 {
let centerPos = LocationCalculation.CenterPoint2(positions: focusNga.points)
mapVC.updateCamera(location: centerPos, zoomlevel: 10.0)
}
}
}
//通知場所を画面中央に表示 //通知場所を画面中央に表示
if let focusPushHistoryId = pushHistory.focusPushHistory, let focusPushHistory = pushHistory.pushHistoryData[focusPushHistoryId]{ if let focusPushHistoryId = pushHistory.focusPushHistory, let focusPushHistory = pushHistory.pushHistoryData[focusPushHistoryId] {
if let position = focusPushHistory.position { if let position = focusPushHistory.position {
if let latitude = position.lat, let longitude = position.lon { if let latitude = position.lat, let longitude = position.lon {
mapVC.updateCamera(location: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), zoomlevel: nil) mapVC.updateCamera(location: CLLocationCoordinate2D(latitude: latitude, longitude: longitude), zoomlevel: nil)
...@@ -56,9 +67,9 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -56,9 +67,9 @@ struct MapRepresentable: UIViewControllerRepresentable{
} }
if let mylocation = location.location { if let mylocation = location.location {
mapVC.updateOwnShip(location: mylocation, bearing: location.heading) mapVC.updateOwnShipSymbol(location: mylocation, bearing: location.heading)
if let ecaArea = ecaArea{ if let ecaArea = ecaArea {
mapVC.updateEcaSwitchingLine(center: mylocation, notice: ecaArea.swNotice, start: ecaArea.swStart, finish: ecaArea.swFinish) mapVC.updateEcaSwitchingLine(center: mylocation, notice: ecaArea.swNotice, start: ecaArea.swStart, finish: ecaArea.swFinish)
} else { } else {
mapVC.removeEcaSwitchingLine() mapVC.removeEcaSwitchingLine()
...@@ -66,26 +77,45 @@ struct MapRepresentable: UIViewControllerRepresentable{ ...@@ -66,26 +77,45 @@ struct MapRepresentable: UIViewControllerRepresentable{
} }
mapVC.updateWakeLines(legLine: map.legLine, portLine: map.portLine, starboardLine: map.starboardLine) mapVC.updateWakeLines(legLine: map.legLine, portLine: map.portLine, starboardLine: map.starboardLine)
mapVC.updateWayPoints(points: map.wayPoints) mapVC.updateWayPoints(points: map.wayPoints)
mapVC.updateEditTarget()
if SharingData.nga.editType == EditNgaType.addPoint || SharingData.nga.editType == EditNgaType.movePoint {
mapVC.updateEditArea(remove: false)
} }
}
class MapViewController : UIViewController{ if SharingData.nga.editType == EditNgaType.registered {
mapVC.updateEditArea(remove: true)
SharingData.nga.editType = EditNgaType.nonEdit
}
internal var mapView: MapView! if SharingData.nga.editType == EditNgaType.deletePoint {
mapVC.updateEditArea(remove: true)
if let no = SharingData.nga.selectPoint {
SharingData.nga.editNga?.points.remove(at: no)
SharingData.nga.selectPoint = nil
}
mapVC.updateEditArea(remove: false)
}
var ownShipSymbol = MapSource(layer: .OwnShip) if SharingData.map.isMapFree == true {
var ecaLine = MapSource(layer: .EcaLine) mapVC.lockEditPoint(isLocked: true)
var ecaSwitchingLine = MapSource(layer: .SwitchingLine) SharingData.map.isMapFree = false
var ecaSwLineLabel = MapSource(layer: .SwLineLabel) }
var wayPoints = MapSource(layer: .WayPoints)
var wakeLines = MapSource(layer: .WakeLines) mapVC.updateAlertArea()
var oneTimeEca = MapSource(layer: .OneTimeEca) }
}
class MapViewController : UIViewController {
internal var mapView: MapView!
internal var touchedFeatures: Feature? = nil
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
let centerCoordinate = CLLocationCoordinate2D(latitude: 37.8, longitude: -96) let centerCoordinate = CLLocationCoordinate2D(latitude: 37.8, longitude: -96)
// let url = StyleURI(rawValue: "mapbox://styles/jmarinecloud/cltrwnk5i01j901ra3g4n7dtz") // let url = StyleURI(rawValue: "mapbox://styles/jmarinecloud/cltrwnk5i01j901ra3g4n7dtz")K
// let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2), styleURI: url) // let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2), styleURI: url)
let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2)) let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2))
mapView = MapView(frame: view.bounds, mapInitOptions: options) mapView = MapView(frame: view.bounds, mapInitOptions: options)
...@@ -93,300 +123,394 @@ class MapViewController : UIViewController{ ...@@ -93,300 +123,394 @@ class MapViewController : UIViewController{
self.view.addSubview(mapView) self.view.addSubview(mapView)
mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in mapView.mapboxMap.onNext(event: .mapLoaded) { [self] _ in
self.addIconImage()
self.addLayers() self.addLayers()
} }
//地図上クリック //地図上クリック
let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleMapTap(sender:))) let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleMapTap(sender:)))
singleTap.numberOfTapsRequired = 1 singleTap.numberOfTapsRequired = 1
for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer { singleTap.numberOfTouchesRequired = 1
singleTap.require(toFail: recognizer) //下記処理を加えると動作しない
} // for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer {
// singleTap.require(toFail: recognizer)
// }
mapView.addGestureRecognizer(singleTap) mapView.addGestureRecognizer(singleTap)
//地図上ダブルクリック
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleMapTap(sender:)))
doubleTap.numberOfTapsRequired = 2
for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer {
doubleTap.require(toFail: recognizer)
}
mapView.addGestureRecognizer(doubleTap)
// 両方を有効にするために必要
singleTap.require(toFail: doubleTap)
//地図上長押し //地図上長押し
let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleMapLongPress(sender:))) let longPress = UILongPressGestureRecognizer(target: self, action: #selector(handleMapLongPress(sender:)))
for recognizer in mapView.gestureRecognizers! where recognizer is UILongPressGestureRecognizer { for recognizer in mapView.gestureRecognizers! where recognizer is UILongPressGestureRecognizer {
longPress.require(toFail: recognizer) longPress.require(toFail: recognizer)
} }
mapView.addGestureRecognizer(longPress) mapView.addGestureRecognizer(longPress)
//地図上ドラッグ
let drug = UIPanGestureRecognizer(target: self, action: #selector(handleMapDrug))
// if isRocked{
mapView.removeGestureRecognizer(drug)
for recognizer in mapView.gestureRecognizers!where recognizer is UIPanGestureRecognizer{
recognizer.isEnabled = true
}
// }else{
// for recognizer in mapView.gestureRecognizers!where recognizer is UIPanGestureRecognizer{
// recognizer.isEnabled = false
// drug.require(toFail: recognizer)
// }
// mapView.addGestureRecognizer(drug)
// }
// updateUserMark()
} }
/** /**
* 地図上クリックアクション * 地図上クリックアクション
*/ */
@objc func handleMapTap(sender: UITapGestureRecognizer) { @objc func handleMapTap(sender: UITapGestureRecognizer) {
print(debug: "called")
// setTapObjInfoDisp(isHidden: true)
// SharingData.UserMark.selectedPointId = nil
// SharingData.UserMark.selectedPointInfo = nil
// SharingData.UserMark.movePointLocation = nil
// setUserMarkRock(isRocked: true)
//
let spot = sender.location(in: mapView) let spot = sender.location(in: mapView)
// mapboxMapManager.targetInfo = nil let coordinate = mapView.mapboxMap.coordinate(for: spot)
// guard let touchedFeature = mapboxMapManager?.mapClick(pos: spot) else { return } mapClick(point: spot, coordinate: coordinate)
// // print(debug: "touchedFeature OK")
// mapboxMapManager.targetInfo = touchedFeature
// guard let type = touchedFeature.attribute(forKey: MapboxMapManager.PropertyKey.ObjectType.rawValue) as? String else { return }
// print(debug: "type = \(type)")
//
// guard let id = touchedFeature.attribute(forKey: MapboxMapManager.PropertyKey.Id.rawValue) else { return }
// print(debug: "id = \(id)")
//
// if let dataType = MapboxMapManager.DataType(rawValue: type){
// updataDetailInfo(type: dataType, id: id)
// switch dataType{
// case .AroundPhone:
// if let id = id as? String{
// //行き先シェア#128
// shareCourceparam.destinationShip = id
// self.destinationShip = id
// performSegue(withIdentifier: ActivityMap.InterruptShareCourse, sender: self)
// }
// default:
// break
// }
// }
} }
/** /**
* 地図上長押しアクション * 地図上長押しアクション
*/ */
@objc func handleMapLongPress(sender: UILongPressGestureRecognizer ){ @objc func handleMapLongPress(sender: UILongPressGestureRecognizer ) {
print( debug: "calld") let spot = sender.location(in: mapView)
// // AIS情報問い合わせ let coordinate = mapView.mapboxMap.coordinate(for: spot)
// //if SharingData.Vessels.distantTimer <= 0 { // 現在表示中でない mapLongClick(point: spot, coordinate: coordinate)
// // 長押し位置の緯度経度を得る
// let spot = sender.location(in: mapView)
// let tapCoordinate: CLLocationCoordinate2D = mapView.convert(spot, toCoordinateFrom: nil)
//
// let semaphore = DispatchSemaphore(value: 0)
// SessionManager().prepareSession(semaphore: semaphore)
//
// DispatchQueue(label: "WebAppRequest").async {
// semaphore.wait()
// self.distantWorkVessel.ErrCnt = 0
// self.distantWorkVessel.RequestWorkVessel( around : false, ActivityMap.noticeWorkVesselDist, tapCoordinate )
// }
// //}
} }
/** /**
* 地図上ドラッグアクション * 地図上ドラッグアクション
*/ */
@objc func handleMapDrug(sender: UIPanGestureRecognizer){ @objc func handleMapDrug(sender: UIPanGestureRecognizer) {
print( debug: "calld") let spot = sender.location(in: mapView)
// if let id = SharingData.UserMark.selectedPointId, let coordinate = mapView.mapboxMap.coordinate(for: spot)
// let point = SharingData.UserMark.selectedPointInfo{ print(debug: "test: handleMapDrug \(coordinate)")
// let pos = sender.location(in: mapView) mapDrug(point: spot, coordinate: coordinate)
// let newLocation = mapView.convert(pos, toCoordinateFrom: nil)
// if sender.state == .began{ if SharingData.nga.editType == EditNgaType.movePoint {
// guard let touchedFeature = mapboxMapManager.mapClick(pos: pos) else { return } if let nga = SharingData.nga.editNga, let no = SharingData.nga.selectPoint {
// guard let type = touchedFeature.attribute(forKey: MapboxMapManager.PropertyKey.ObjectType.rawValue) as? String else { return } var ngaData = nga
// if let _ = touchedFeature.attribute(forKey: MapboxMapManager.PropertyKey.Id.rawValue) as? Int64, ngaData.points[no] = coordinate
// type == MapboxMapManager.DataType.UserMark.rawValue && SharingData.nga.targetLocation = coordinate
// id == SharingData.UserMark.selectedPointId{ SharingData.nga.editNga = ngaData
// SharingData.UserMark.movePointLocation = newLocation updateEditArea()
// }
// }else if let _ = SharingData.UserMark.movePointLocation,
// let _ = SharingData.UserMark.selectedPointId{
// if sender.state == .changed{
// SharingData.UserMark.movePointLocation = newLocation
// }else if sender.state == .ended{
// let markManager = UserMarkManager()
// point.latitude = newLocation.latitude
// point.longitude = newLocation.longitude
// markManager.updatePoint(point: point)
// updateUserMarkDetail(point: point)
// SharingData.UserMark.movePointLocation = nil
// }
// }
// }
// updateUserMark()
// updateRootNavigation()
// mapboxMapManager.updateTarget()
}
/**
* 自船アイコンの状態表記
*/
func addImage(){
do{
if let image = UIImage(named: "ownShip_normal"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Normal.rawValue)
}
if let image = UIImage(named: "ownShip_alarm"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Alarm.rawValue)
}
if let image = UIImage(named: "ownShip_caution"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Caution.rawValue)
}
if let image = UIImage(named: "ownShip_emergency"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Emergency.rawValue)
}
if let image = UIImage(named: "ownShip_necstemergency"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_NeCST_Emergency.rawValue)
} }
if let image = UIImage(named: "ownShip_offline"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Offline.rawValue)
} }
if let image = UIImage(named: "ownShip_unknown"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Unknown.rawValue)
} }
if let image = UIImage(named: "ownShip_warning"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.OwnShip_Warning.rawValue) /**
* アイコンの状態表記
*/
let IconImageList = [
IconImageData(name: "ownShip_normal", id: IconImage.OwnShip_Normal.rawValue),
IconImageData(name: "ownShip_alarm", id: IconImage.OwnShip_Alarm.rawValue),
IconImageData(name: "ownShip_caution", id: IconImage.OwnShip_Caution.rawValue),
IconImageData(name: "ownShip_emergency", id: IconImage.OwnShip_Emergency.rawValue),
IconImageData(name: "ownShip_necstemergency", id: IconImage.OwnShip_NeCST_Emergency.rawValue),
IconImageData(name: "ownShip_offline", id: IconImage.OwnShip_Offline.rawValue),
IconImageData(name: "ownShip_unknown", id: IconImage.OwnShip_Unknown.rawValue),
IconImageData(name: "ownShip_warning", id: IconImage.OwnShip_Warning.rawValue),
IconImageData(name: "swNoticeBack", id: IconImage.SwNoticeBack.rawValue),
IconImageData(name: "swStartBack", id: IconImage.SwStartBack.rawValue),
IconImageData(name: "swFinishBack", id: IconImage.SwFinisheBack.rawValue),
IconImageData(name: "areaPoint", id: IconImage.AreaPoint.rawValue),
IconImageData(name: "target", id: IconImage.Target.rawValue),
IconImageData(name: "addSymbol", id: IconImage.AddSymbol.rawValue)
]
enum IconImage: String, CaseIterable {
case OwnShip_Alarm
case OwnShip_Caution
case OwnShip_Emergency
case OwnShip_NeCST_Emergency
case OwnShip_Normal
case OwnShip_Offline
case OwnShip_Unknown
case OwnShip_Warning
case SwNoticeBack
case SwStartBack
case SwFinisheBack
case AreaPoint
case Target
case AddSymbol
} }
if let image = UIImage(named: "swNoticeBack"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.SwNoticeBack.rawValue) struct IconImageData {
var name: String
var id: String
} }
if let image = UIImage(named: "swStartBack"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.SwStartBack.rawValue) func addIconImage() {
do{
for iconData in IconImageList {
if let iconImage = UIImage(named: iconData.name) {
try mapView.mapboxMap.style.addImage(iconImage, id: iconData.id)
} }
if let image = UIImage(named: "swFinishBack"){
try mapView.mapboxMap.style.addImage(image, id: IconImage.SwFinisheBack.rawValue)
} }
} catch { } catch {
print(debug: "called") print(debug: "called")
} }
} }
func addLayers(){ /**
* レイヤー処理
*/
enum LayerEnum: String {
case OwnShipSymbol
case EcaLine
case SwitchingLine
case SwLineLabel
case WayPoints
case WakeLines
case OneTimeEca
case EditTargetSymbol
case EditAreaAddSymbol
case EditAreaSymbol
case EditAreaLine
case EditAreaFill
case AlertAreaLabel
case AlertAreaSymbol
case AlertAreaLine
case AlertAreaFill
}
addImage() var ownShipSymbol = MapSource(layer: .OwnShipSymbol)
var ecaLine = MapSource(layer: .EcaLine)
var ecaSwitchingLine = MapSource(layer: .SwitchingLine)
var ecaSwLineLabel = MapSource(layer: .SwLineLabel)
var wayPoints = MapSource(layer: .WayPoints)
var wakeLines = MapSource(layer: .WakeLines)
var oneTimeEca = MapSource(layer: .OneTimeEca)
var editTargetSymbol = MapSource(layer: .EditTargetSymbol)
var editAreaAddSymbol = MapSource(layer: .EditAreaAddSymbol)
var editAreaFill = MapSource(layer: .EditAreaFill)
var editAreaLine = MapSource(layer: .EditAreaLine)
var editAreaSymbol = MapSource(layer: .EditAreaSymbol)
var alertAreaLabel = MapSource(layer: .AlertAreaLabel)
var alertAreaFill = MapSource(layer: .AlertAreaFill)
var alertAreaLine = MapSource(layer: .AlertAreaLine)
var alertAreaSymbol = MapSource(layer: .AlertAreaSymbol)
/**
* レイヤー作成
*/
func addLayers() {
alertAreaFillLayer()
alertAreaLineLayer()
editAreaFillLayer()
editAreaLineLayer()
editAreaAddSymbolLayer()
editAreaSymbolLayer()
editTargetSymbolLayer()
wayPointsLayer()
wakeLineLayer() //航路ライン
ecaSwitchingLineLabelLayer()
ecaSwitchingLineLayer()
oneTimeEcaLineLayer()
ecaLineLayer() //ECAライン
ownShipSymbolLayer() //自船シンボル
}
//自船 /**
* 自船シンボル表示レイヤー
*/
private func ownShipSymbolLayer() {
let point = Point(LocationCoordinate2D(latitude: 0, longitude: 0)) let point = Point(LocationCoordinate2D(latitude: 0, longitude: 0))
ownShipSymbol.source.data = .feature(Feature(geometry: point)) ownShipSymbol.source.data = .feature(Feature(geometry: point))
try! mapView.mapboxMap.style.addSource(ownShipSymbol.source, id: ownShipSymbol.sourceId)
var ownShipSymbolLayer = SymbolLayer(id: ownShipSymbol.layerId) var ownShipSymbolLayer = SymbolLayer(id: ownShipSymbol.layerId)
ownShipSymbolLayer.source = ownShipSymbol.sourceId ownShipSymbolLayer.source = ownShipSymbol.sourceId
ownShipSymbolLayer.iconImage = .expression(Exp(.get) { ownShipSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
PropertyKey.IconImage.rawValue
})
ownShipSymbolLayer.iconRotationAlignment = .constant(.map) ownShipSymbolLayer.iconRotationAlignment = .constant(.map)
ownShipSymbolLayer.iconAllowOverlap = .constant(true) ownShipSymbolLayer.iconAllowOverlap = .constant(true)
ownShipSymbolLayer.iconIgnorePlacement = .constant(true) ownShipSymbolLayer.iconIgnorePlacement = .constant(true)
ownShipSymbolLayer.iconRotate = .expression(Exp(.get) { ownShipSymbolLayer.iconRotate = .expression(Exp(.get) {PropertyKey.Bearing.rawValue})
PropertyKey.Bearing.rawValue
})
try! mapView.mapboxMap.style.addSource(ownShipSymbol.source, id: ownShipSymbol.sourceId)
try? mapView.mapboxMap.style.addLayer(ownShipSymbolLayer) try? mapView.mapboxMap.style.addLayer(ownShipSymbolLayer)
}
//ECA /**
* ECAライン表示レイヤー
*/
private func ecaLineLayer() {
let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)]) let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)])
let ecaLinefeature = Feature(geometry: ecaLineString) let ecaLinefeature = Feature(geometry: ecaLineString)
ecaLine.source.data = .feature(ecaLinefeature) ecaLine.source.data = .feature(ecaLinefeature)
try! mapView.mapboxMap.style.addSource(ecaLine.source, id: ecaLine.sourceId)
var ecaLineLayer = LineLayer(id: ecaLine.layerId) var ecaLineLayer = LineLayer(id: ecaLine.layerId)
ecaLineLayer.source = ecaLine.sourceId ecaLineLayer.source = ecaLine.sourceId
ecaLineLayer.lineColor = .expression(Exp(.get) { ecaLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
PropertyKey.Color.rawValue
})
ecaLineLayer.lineDasharray = .constant([2,1]) ecaLineLayer.lineDasharray = .constant([2,1])
try! mapView.mapboxMap.style.addSource(ecaLine.source, id: ecaLine.sourceId)
try? mapView.mapboxMap.style.addLayer(ecaLineLayer) try? mapView.mapboxMap.style.addLayer(ecaLineLayer)
}
// /**
_ = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)]) * ECAライン一時表示レイヤー
*/
private func oneTimeEcaLineLayer() {
let ecaLineString = LineString([LocationCoordinate2D(latitude: 0, longitude: 0)])
let oneTimeEcaLinefeature = Feature(geometry: ecaLineString) let oneTimeEcaLinefeature = Feature(geometry: ecaLineString)
oneTimeEca.source.data = .feature(oneTimeEcaLinefeature) oneTimeEca.source.data = .feature(oneTimeEcaLinefeature)
try! mapView.mapboxMap.style.addSource(oneTimeEca.source, id: oneTimeEca.sourceId)
var oneTimeEcaLayer = LineLayer(id: oneTimeEca.layerId) var oneTimeEcaLayer = LineLayer(id: oneTimeEca.layerId)
oneTimeEcaLayer.source = oneTimeEca.sourceId oneTimeEcaLayer.source = oneTimeEca.sourceId
oneTimeEcaLayer.lineColor = .expression(Exp(.get) { oneTimeEcaLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
PropertyKey.Color.rawValue
})
oneTimeEcaLayer.lineDasharray = .constant([2,1]) oneTimeEcaLayer.lineDasharray = .constant([2,1])
try! mapView.mapboxMap.style.addSource(oneTimeEca.source, id: oneTimeEca.sourceId)
try? mapView.mapboxMap.style.addLayer(oneTimeEcaLayer) try? mapView.mapboxMap.style.addLayer(oneTimeEcaLayer)
}
// /**
* ECA切替ライン表示レイヤー
*/
private func ecaSwitchingLineLayer() {
ecaSwitchingLine.source.data = .featureCollection(FeatureCollection(features: [])) ecaSwitchingLine.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(ecaSwitchingLine.source, id: ecaSwitchingLine.sourceId)
var ecaSwitchingLineLayer = LineLayer(id: ecaSwitchingLine.layerId) var ecaSwitchingLineLayer = LineLayer(id: ecaSwitchingLine.layerId)
ecaSwitchingLineLayer.source = ecaSwitchingLine.sourceId ecaSwitchingLineLayer.source = ecaSwitchingLine.sourceId
ecaSwitchingLineLayer.lineColor = .expression(Exp(.get) { ecaSwitchingLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
PropertyKey.Color.rawValue
})
ecaSwitchingLineLayer.lineDasharray = .constant([2,1]) ecaSwitchingLineLayer.lineDasharray = .constant([2,1])
try! mapView.mapboxMap.style.addSource(ecaSwitchingLine.source, id: ecaSwitchingLine.sourceId)
try? mapView.mapboxMap.style.addLayer(ecaSwitchingLineLayer) try? mapView.mapboxMap.style.addLayer(ecaSwitchingLineLayer)
}
//ECA ラベル /**
* ECA切替ラインラベル表示レイヤー
*/
private func ecaSwitchingLineLabelLayer() {
ecaSwLineLabel.source.data = .featureCollection(FeatureCollection(features: [])) ecaSwLineLabel.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(ecaSwLineLabel.source, id: ecaSwLineLabel.sourceId)
var ecaSwLabelLayer = SymbolLayer(id: ecaSwLineLabel.layerId) var ecaSwLabelLayer = SymbolLayer(id: ecaSwLineLabel.layerId)
ecaSwLabelLayer.source = ecaSwLineLabel.sourceId ecaSwLabelLayer.source = ecaSwLineLabel.sourceId
ecaSwLabelLayer.textField = .expression(Exp(.get) { ecaSwLabelLayer.textField = .expression(Exp(.get) {PropertyKey.Text.rawValue})
PropertyKey.Text.rawValue ecaSwLabelLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
}) ecaSwLabelLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
ecaSwLabelLayer.iconImage = .expression(Exp(.get) {
PropertyKey.IconImage.rawValue
})
ecaSwLabelLayer.iconColor = .expression(Exp(.get) {
PropertyKey.Color.rawValue
})
ecaSwLabelLayer.iconTextFit = .constant(.both) ecaSwLabelLayer.iconTextFit = .constant(.both)
ecaSwLabelLayer.iconTextFitPadding = .constant([0,6,0,6]) ecaSwLabelLayer.iconTextFitPadding = .constant([0,6,0,6])
try! mapView.mapboxMap.style.addSource(ecaSwLineLabel.source, id: ecaSwLineLabel.sourceId)
try? mapView.mapboxMap.style.addLayer(ecaSwLabelLayer) try? mapView.mapboxMap.style.addLayer(ecaSwLabelLayer)
}
//航路 /**
* 航跡ラインレイヤー
*/
private func wakeLineLayer() {
wakeLines.source.data = .featureCollection(FeatureCollection(features: [])) wakeLines.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(wakeLines.source, id: wakeLines.sourceId)
var wakeLineLayer = LineLayer(id: wakeLines.layerId) var wakeLineLayer = LineLayer(id: wakeLines.layerId)
wakeLineLayer.source = wakeLines.sourceId wakeLineLayer.source = wakeLines.sourceId
wakeLineLayer.lineColor = .expression(Exp(.get) { wakeLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
PropertyKey.Color.rawValue
})
try! mapView.mapboxMap.style.addSource(wakeLines.source, id: wakeLines.sourceId)
try? mapView.mapboxMap.style.addLayer(wakeLineLayer) try? mapView.mapboxMap.style.addLayer(wakeLineLayer)
}
//WayPoint /**
* wayポイントレイヤー
*/
private func wayPointsLayer() {
wayPoints.source.data = .featureCollection(FeatureCollection(features: [])) wayPoints.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(wayPoints.source, id: wayPoints.sourceId)
var wayPointsLayer = SymbolLayer(id: wayPoints.layerId) var wayPointsLayer = SymbolLayer(id: wayPoints.layerId)
wayPointsLayer.source = wayPoints.sourceId wayPointsLayer.source = wayPoints.sourceId
wayPointsLayer.iconImage = .expression(Exp(.get) { wayPointsLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
PropertyKey.IconImage.rawValue wayPointsLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
})
wayPointsLayer.iconColor = .expression(Exp(.get) {
PropertyKey.Color.rawValue
})
try! mapView.mapboxMap.style.addSource(wayPoints.source, id: wayPoints.sourceId)
try? mapView.mapboxMap.style.addLayer(wayPointsLayer) try? mapView.mapboxMap.style.addLayer(wayPointsLayer)
} }
///自船 /**
func updateOwnShip(location: CLLocationCoordinate2D, bearing: Double){ * NGA Editターゲットレイヤー
*/
private func editTargetSymbolLayer() {
editTargetSymbol.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(editTargetSymbol.source, id: editTargetSymbol.sourceId)
var editTargetSymbolLayer = SymbolLayer(id: editTargetSymbol.layerId)
editTargetSymbolLayer.source = editTargetSymbol.sourceId
editTargetSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
editTargetSymbolLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
try? mapView.mapboxMap.style.addLayer(editTargetSymbolLayer)
}
/**
* NGA Edit追加シンボルレイヤー
*/
private func editAreaAddSymbolLayer() {
editAreaAddSymbol.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(editAreaAddSymbol.source, id: editAreaAddSymbol.sourceId)
var editAreaAddSymbolLayer = SymbolLayer(id: editAreaAddSymbol.layerId)
editAreaAddSymbolLayer.source = editAreaAddSymbol.sourceId
editAreaAddSymbolLayer.textField = .expression(Exp(.get) {PropertyKey.Text.rawValue})
editAreaAddSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
editAreaAddSymbolLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
// editAreaSymbolLayer.iconOffset
// editAreaSymbolLayer.textOffset
try? mapView.mapboxMap.style.addLayer(editAreaAddSymbolLayer)
}
/**
* NGA Editポイントレイヤー
*/
private func editAreaSymbolLayer() {
editAreaSymbol.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(editAreaSymbol.source, id: editAreaSymbol.sourceId)
var editAreaSymbolLayer = SymbolLayer(id: editAreaSymbol.layerId)
editAreaSymbolLayer.source = editAreaSymbol.sourceId
editAreaSymbolLayer.textField = .expression(Exp(.get) {PropertyKey.Text.rawValue})
editAreaSymbolLayer.iconImage = .expression(Exp(.get) {PropertyKey.IconImage.rawValue})
editAreaSymbolLayer.iconColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
// editAreaSymbolLayer.iconOffset
// editAreaSymbolLayer.textOffset
try? mapView.mapboxMap.style.addLayer(editAreaSymbolLayer)
}
/**
* NGA Editライン表示レイヤー
*/
private func editAreaLineLayer() {
editAreaLine.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(editAreaLine.source, id: editAreaLine.sourceId)
var editAreaLineLayer = LineLayer(id: editAreaLine.layerId)
editAreaLineLayer.source = editAreaLine.sourceId
editAreaLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
editAreaLineLayer.lineWidth = .expression(Exp(.get) {PropertyKey.LineWidth.rawValue})
try? mapView.mapboxMap.style.addLayer(editAreaLineLayer)
}
/**
* NGA Editエリアレイヤー
*/
private func editAreaFillLayer() {
editAreaFill.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(editAreaFill.source, id: editAreaFill.sourceId)
var editAreaFillLayer = FillLayer(id: editAreaFill.layerId)
editAreaFillLayer.source = editAreaFill.sourceId
editAreaFillLayer.fillColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
try? mapView.mapboxMap.style.addLayer(editAreaFillLayer)
}
/**
* NGAライン表示レイヤー
*/
private func alertAreaLineLayer() {
alertAreaLine.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(alertAreaLine.source, id: alertAreaLine.sourceId)
var alertAreaLineLayer = LineLayer(id: alertAreaLine.layerId)
alertAreaLineLayer.source = alertAreaLine.sourceId
alertAreaLineLayer.lineColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
alertAreaLineLayer.lineWidth = .expression(Exp(.get) {PropertyKey.LineWidth.rawValue})
try? mapView.mapboxMap.style.addLayer(alertAreaLineLayer)
}
/**
* NGA エリアレイヤー
*/
private func alertAreaFillLayer() {
alertAreaFill.source.data = .featureCollection(FeatureCollection(features: []))
try! mapView.mapboxMap.style.addSource(alertAreaFill.source, id: alertAreaFill.sourceId)
var alertAreaFillLayer = FillLayer(id: alertAreaFill.layerId)
alertAreaFillLayer.source = alertAreaFill.sourceId
alertAreaFillLayer.fillColor = .expression(Exp(.get) {PropertyKey.Color.rawValue})
alertAreaFillLayer.fillOpacity = .expression(Exp(.get) {PropertyKey.FillOpacity.rawValue})
try? mapView.mapboxMap.style.addLayer(alertAreaFillLayer)
}
/**
* 自船シンボル描画処理
*/
func updateOwnShipSymbol(location: CLLocationCoordinate2D, bearing: Double){
do { do {
var shipIcon = IconImage.OwnShip_Normal.rawValue var shipIcon = IconImage.OwnShip_Normal.rawValue
...@@ -418,26 +542,10 @@ class MapViewController : UIViewController{ ...@@ -418,26 +542,10 @@ class MapViewController : UIViewController{
} }
} }
///カメラ /**
func updateCamera(location: CLLocationCoordinate2D?, zoomlevel: CGFloat?){ * ECA表示
if let level = zoomlevel { */
self.mapView.camera.ease(to: CameraOptions(center: location, zoom: level), duration: 1) func updateEcaSwitchingLine(center: CLLocationCoordinate2D, notice: Float, start: Float, finish: Float) {
} else {
self.mapView.camera.ease(to: CameraOptions(center: location), duration: 1)
}
if SharingData.eca.focusEca != nil {
SharingData.eca.focusEca = nil
}
if SharingData.pushHistory.focusPushHistory != nil {
SharingData.pushHistory.focusPushHistory = nil
}
if SharingData.location.focusOwnShip {
SharingData.location.focusOwnShip = false
}
}
///Ecaの線3本
func updateEcaSwitchingLine(center: CLLocationCoordinate2D, notice: Float, start: Float, finish: Float){
do{ do{
var switchingLines : [Feature] = [] var switchingLines : [Feature] = []
var switchingLabels : [Feature] = [] var switchingLabels : [Feature] = []
...@@ -454,7 +562,6 @@ class MapViewController : UIViewController{ ...@@ -454,7 +562,6 @@ class MapViewController : UIViewController{
switchingLabels.append(label) switchingLabels.append(label)
} }
let circlePoints_start = getCirclePoints(center: center, radiusKm: LocationCalculation.nm2km(nm: Double(start))) let circlePoints_start = getCirclePoints(center: center, radiusKm: LocationCalculation.nm2km(nm: Double(start)))
var startLine = Feature(geometry: LineString(circlePoints_start)) var startLine = Feature(geometry: LineString(circlePoints_start))
startLine.properties = [PropertyKey.Color.rawValue: .string("#ECD932")] startLine.properties = [PropertyKey.Color.rawValue: .string("#ECD932")]
...@@ -483,10 +590,15 @@ class MapViewController : UIViewController{ ...@@ -483,10 +590,15 @@ class MapViewController : UIViewController{
let labelGeoJson = FeatureCollection(features: switchingLabels) let labelGeoJson = FeatureCollection(features: switchingLabels)
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson))
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson))
}catch{} } catch {
print(debug: "called")
}
} }
func removeEcaSwitchingLine(){ /**
* ECA消去
*/
func removeEcaSwitchingLine() {
do{ do{
let switchingLines : [Feature] = [] let switchingLines : [Feature] = []
let switchingLabels : [Feature] = [] let switchingLabels : [Feature] = []
...@@ -495,55 +607,55 @@ class MapViewController : UIViewController{ ...@@ -495,55 +607,55 @@ class MapViewController : UIViewController{
let labelGeoJson = FeatureCollection(features: switchingLabels) let labelGeoJson = FeatureCollection(features: switchingLabels)
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwitchingLine.sourceId, geoJSON: .featureCollection(lineGeoJson))
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(labelGeoJson))
}catch{} } catch {
} print(debug: "called")
///円の位置情報を返す
private func getCirclePoints(center: CLLocationCoordinate2D, radiusKm: Double) -> [CLLocationCoordinate2D]{
var circlePoints : [CLLocationCoordinate2D] = []
for deg in stride(from: 0, through: 360, by: 6) {
let point = LocationCalculation.findPointAtDistanceFrom(
startPointLat: center.latitude,
startPointLon: center.longitude,
initialBearing: Double(deg),
distanceKilometers: radiusKm
)
circlePoints.append(point)
} }
return circlePoints
} }
func updateEcaLine(line: [CLLocationCoordinate2D]){ /**
* ECAライン更新
*/
func updateEcaLine(line: [CLLocationCoordinate2D]) {
do{ do{
var geoJson = Feature(geometry: LineString(line)) var geoJson = Feature(geometry: LineString(line))
geoJson.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)] geoJson.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson))
}catch{} } catch {
print(debug: "called")
}
} }
/**
* ECAライン消去
*/
func removeEcaLine(){ func removeEcaLine(){
do{ do{
let line: [CLLocationCoordinate2D] = [] let line: [CLLocationCoordinate2D] = []
let geoJson = Feature(geometry: LineString(line)) let geoJson = Feature(geometry: LineString(line))
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaLine.sourceId, geoJSON: .feature(geoJson))
}catch{} } catch {
print(debug: "called")
}
} }
///一時的に見たいEcaを表示 ///一時的に見たいEcaを表示
func updateOneTimeEca(eca: [CLLocationCoordinate2D]?){ func updateOneTimeEca(eca: [CLLocationCoordinate2D]?) {
do{ do {
let eca = eca ?? [] let eca = eca ?? []
var geoJson = Feature(geometry: LineString(eca)) var geoJson = Feature(geometry: LineString(eca))
geoJson.properties = [PropertyKey.Color.rawValue: .string(Color.black.description)] geoJson.properties = [PropertyKey.Color.rawValue: .string(Color.black.description)]
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: oneTimeEca.sourceId, geoJSON: .feature(geoJson)) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: oneTimeEca.sourceId, geoJSON: .feature(geoJson))
}catch{ } catch {
print(debug: "called")
} }
} }
func updateWakeLines(legLine: [CLLocationCoordinate2D], portLine: [CLLocationCoordinate2D], starboardLine: [CLLocationCoordinate2D]){ /**
* 航跡ライン更新処理
*/
func updateWakeLines(legLine: [CLLocationCoordinate2D], portLine: [CLLocationCoordinate2D], starboardLine: [CLLocationCoordinate2D]) {
do{ do{
var legLineFeature = Feature(geometry: LineString(legLine)) var legLineFeature = Feature(geometry: LineString(legLine))
legLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)] legLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]
...@@ -555,11 +667,359 @@ class MapViewController : UIViewController{ ...@@ -555,11 +667,359 @@ class MapViewController : UIViewController{
starboardLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)] starboardLineFeature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: wakeLines.sourceId, geoJSON: .featureCollection(FeatureCollection(features: [legLineFeature, portLineFeature, starboardLineFeature]))) try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: wakeLines.sourceId, geoJSON: .featureCollection(FeatureCollection(features: [legLineFeature, portLineFeature, starboardLineFeature])))
}catch{} } catch {
print(debug: "called")
}
}
/**
* wayポイント更新処理
*/
func updateWayPoints(points: [CLLocationCoordinate2D]) {
do {
var features : [Feature] = []
for point in points {
var feature = Feature(geometry: Point(point))
feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.SwFinisheBack.rawValue),
PropertyKey.Color.rawValue: .string("#EF6135")]
features.append(feature)
}
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
} catch {
print(debug: "called")
}
}
/**
* NGA Editターゲット更新処理
*/
private func updateEditTargetSymbol(point: CLLocationCoordinate2D, remove: Bool = false) {
do {
var features : [Feature] = []
if remove == false {
var feature = Feature(geometry: Point(point))
feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.Target.rawValue),
PropertyKey.Color.rawValue: .string("#EF6135")]
features.append(feature)
}
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editTargetSymbol.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
} catch {
print(debug: "called")
}
}
/**
* NGA Edit更新処理
* remove:
* true:画面消去
* false:画面表示
*/
func updateEditArea(remove: Bool = false) {
if let area = SharingData.nga.editNga {
if remove {
updateEditAreaAddSymbol(points: area.points, remove: remove)
updateEditAreaSymbol(points: area.points, remove: remove)
updateEditAreaLine(points: area.points, remove: remove)
updateEditAreaFill(points: area.points, remove: remove)
} else {
if area.points.count != 0 {
// updateEditAreaLabel(points: points)
updateEditAreaSymbol(points: area.points, remove: remove)
}
if area.points.count >= 2 {
updateEditAreaLine(points: area.points, remove: remove)
}
var areaPoints: [CLLocationCoordinate2D] = []
if remove == true {
updateEditAreaFill(points: areaPoints, remove: remove)
updateEditAreaAddSymbol(points: areaPoints, remove: remove)
} else {
if area.points.count >= 3 {
areaPoints = area.points
areaPoints.append(area.points[0])
updateEditAreaFill(points: areaPoints, remove: true)
updateEditAreaFill(points: areaPoints, remove: false)
updateEditAreaAddSymbol(points: areaPoints, remove: false)
}
}
}
}
}
func updateEditTarget() {
if SharingData.nga.editType == EditNgaType.movePoint {
if let location = SharingData.nga.targetLocation {
updateEditTargetSymbol(point: location)
}
} else {
let location = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
updateEditTargetSymbol(point: location, remove: true)
}
}
/**
* NGA Edit 追加シンボル更新処理
*/
private func updateEditAreaAddSymbol(points: [CLLocationCoordinate2D], remove: Bool = false) {
do{
var features : [Feature] = []
var id = 1
var firstPass = false
if remove == false {
var pointA = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
var pointB = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
for point in points {
if firstPass == true {
pointB = point
let harf = LocationCalculation.halfPoint(posA: pointA, posB: pointB)
var feature = Feature(geometry: Point(harf))
feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.AddSymbol.rawValue),
PropertyKey.Id.rawValue: .string(String(id)),
PropertyKey.Dtype.rawValue: .string(DataType.add.rawValue),
PropertyKey.Color.rawValue: .string("#62AB28")]
features.append(feature)
id += 1
pointA = pointB
} else {
pointA = point
firstPass = true
}
}
}
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaAddSymbol.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
} catch {
print(debug: "called")
}
}
/**
* NGA Editポイント更新処理
*/
private func updateEditAreaSymbol(points: [CLLocationCoordinate2D], remove: Bool = false) {
do {
var features : [Feature] = []
var id = 0
if remove == false {
for point in points {
var feature = Feature(geometry: Point(point))
feature.properties = [PropertyKey.Text.rawValue: .string(String(id)),
PropertyKey.IconImage.rawValue: .string(IconImage.AreaPoint.rawValue),
PropertyKey.Id.rawValue: .string(String(id)),
PropertyKey.Dtype.rawValue: .string(DataType.point.rawValue),
PropertyKey.Color.rawValue: .string("#EF6135")]
features.append(feature)
id += 1
}
}
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaSymbol.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
} catch {
print(debug: "called")
}
}
/**
* NGA Editライン更新処理
*/
private func updateEditAreaLine(points: [CLLocationCoordinate2D], remove: Bool = false) {
do {
var features : [Feature] = []
var id = 0
if remove == false {
if points.count >= 3 {
for cnt in 0..<points.count {
var line : [CLLocationCoordinate2D] = []
line.append(points[cnt])
if cnt + 1 == points.count {
line.append(points[0])
} else {
line.append(points[cnt + 1])
}
var feature = Feature(geometry: LineString(line))
feature.properties = [PropertyKey.Color.rawValue: .string(Color.black.description),
PropertyKey.Id.rawValue: .string(String(id)),
PropertyKey.Dtype.rawValue: .string(DataType.line.rawValue),
PropertyKey.LineWidth.rawValue: 3.0]
features.append(feature)
id += 1
}
} else if points.count == 2 {
var line : [CLLocationCoordinate2D] = []
line.append(points[0])
line.append(points[1])
var feature = Feature(geometry: LineString(line))
feature.properties = [PropertyKey.Color.rawValue: .string(Color.black.description),
PropertyKey.Id.rawValue: .string(String(id)),
PropertyKey.Dtype.rawValue: .string(DataType.line.rawValue),
PropertyKey.LineWidth.rawValue: 1.0]
features.append(feature)
}
}
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaLine.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
} catch {
print(debug: "called")
}
}
/**
* NGA Editエリア更新処理
*/
private func updateEditAreaFill(points: [CLLocationCoordinate2D], remove: Bool = false) {
do{
var features : [Feature] = []
if remove == false {
var cnvPoints: Array<Array<CLLocationCoordinate2D>> = []
var areaPoints = points
let firstPoint = points[0]
areaPoints.append(firstPoint)
cnvPoints.append(areaPoints)
var feature = Feature(geometry: Polygon(cnvPoints))
feature.properties = [PropertyKey.Color.rawValue: .string(Color.blue.description)]
features.append(feature)
}
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: editAreaFill.sourceId, geoJSON: .featureCollection(FeatureCollection(features: features)))
} catch {
print(debug: "called")
}
}
/**
* NGA 更新処理
*/
func updateAlertArea() {
updateAlertAreaLine(area: SharingData.nga.ngaArea)
updateAlertAreaFill(area: SharingData.nga.ngaArea)
}
/**
* NGA ポイント更新処理
*/
private func updateAlertAreaSymbol(area: Dictionary<UUID, RegisteredNga>) {
do{
var features : [Feature] = []
for (_, value) in area {
if value.points.count >= 3 {
for point in value.points {
var feature = Feature(geometry: Point(point))
feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.AreaPoint.rawValue),
PropertyKey.Color.rawValue: .string(Color.black.description)]
features.append(feature)
}
}
}
let featureCollection = FeatureCollection(features: features)
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: alertAreaSymbol.sourceId, geoJSON: .featureCollection(featureCollection))
} catch {
print(debug: "called")
}
}
/**
* NGAライン更新処理
*/
private func updateAlertAreaLine(area: Dictionary<UUID, RegisteredNga>) {
do{
var features : [Feature] = []
for (_, value) in area {
if value.isRunning == true {
if value.points.count >= 3 {
var areaPoints = value.points
let firstPoint = value.points[0]
areaPoints.append(firstPoint)
var color = Color.white.description
if value.isRunning {
color = Color.red.description
}
var feature = Feature(geometry: LineString(areaPoints))
feature.properties = [PropertyKey.Color.rawValue: .string(color),
PropertyKey.LineWidth.rawValue: 1.0]
features.append(feature)
}
}
}
let featureCollection = FeatureCollection(features: features)
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: alertAreaLine.sourceId, geoJSON: .featureCollection(featureCollection))
} catch {
print(debug: "called")
}
}
/**
* NGA エリア更新処理
*/
private func updateAlertAreaFill(area: Dictionary<UUID, RegisteredNga>) {
do{
var features : [Feature] = []
for (_, value) in area {
if value.points.count >= 3 {
var cnvPoints: Array<Array<CLLocationCoordinate2D>> = []
var areaPoints = value.points
let firstPoint = value.points[0]
areaPoints.append(firstPoint)
cnvPoints.append(areaPoints)
var feature = Feature(geometry: Polygon(cnvPoints))
if value.isRunning {
feature.properties = [PropertyKey.Color.rawValue: .string(value.color),
PropertyKey.FillOpacity.rawValue: 1.0]
} else {
feature.properties = [PropertyKey.Color.rawValue: .string(value.color),
PropertyKey.FillOpacity.rawValue: 0.2]
}
features.append(feature)
}
}
let featureCollection = FeatureCollection(features: features)
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: alertAreaFill.sourceId, geoJSON: .featureCollection(featureCollection))
} catch {
print(debug: "called")
}
}
/**
* カメラ
*/
func updateCamera(location: CLLocationCoordinate2D?, zoomlevel: CGFloat?){
if let level = zoomlevel {
self.mapView.camera.ease(to: CameraOptions(center: location, zoom: level), duration: 1)
} else {
self.mapView.camera.ease(to: CameraOptions(center: location), duration: 1)
}
if SharingData.eca.focusEca != nil {
SharingData.eca.focusEca = nil
}
if SharingData.nga.focusNga != nil {
SharingData.nga.focusNga = nil
}
if SharingData.pushHistory.focusPushHistory != nil {
SharingData.pushHistory.focusPushHistory = nil
}
if SharingData.location.focusOwnShip {
SharingData.location.focusOwnShip = false
}
} }
///子午線を跨ぐ位置情報をチェックして東経ベースに補正する。 /**
static func checkStraddleMeridian(_ locations: [CLLocationCoordinate2D]) -> [CLLocationCoordinate2D]{ * 子午線を跨ぐ位置情報をチェックして東経ベースに補正する。
*/
static func checkStraddleMeridian(_ locations: [CLLocationCoordinate2D]) -> [CLLocationCoordinate2D] {
let eastLon = FloatingPointSign.plus let eastLon = FloatingPointSign.plus
var returnLocations : [CLLocationCoordinate2D] = [] var returnLocations : [CLLocationCoordinate2D] = []
for location in locations { for location in locations {
...@@ -571,44 +1031,237 @@ class MapViewController : UIViewController{ ...@@ -571,44 +1031,237 @@ class MapViewController : UIViewController{
returnLocations.append(location) returnLocations.append(location)
} }
} }
return returnLocations return returnLocations
} }
func updateWayPoints(points: [CLLocationCoordinate2D]){ /**
do{ * 円の位置情報を返す
var wayPointsFeatures : [Feature] = [] */
private func getCirclePoints(center: CLLocationCoordinate2D, radiusKm: Double) -> [CLLocationCoordinate2D]{
for point in points{ var circlePoints : [CLLocationCoordinate2D] = []
var feature = Feature(geometry: Point(point)) for deg in stride(from: 0, through: 360, by: 6) {
feature.properties = [PropertyKey.IconImage.rawValue: .string(IconImage.SwFinisheBack.rawValue), let point = LocationCalculation.findPointAtDistanceFrom(
PropertyKey.Color.rawValue: .string("#EF6135")] startPointLat: center.latitude,
wayPointsFeatures.append(feature) startPointLon: center.longitude,
initialBearing: Double(deg),
distanceKilometers: radiusKm
)
circlePoints.append(point)
} }
return circlePoints
try self.mapView.mapboxMap.style.updateGeoJSONSource(withId: ecaSwLineLabel.sourceId, geoJSON: .featureCollection(FeatureCollection(features: wayPointsFeatures)))
}catch{}
} }
enum PropertyKey : String { enum PropertyKey : String {
case Id
case Dtype
case IconImage case IconImage
case Bearing case Bearing
case Color case Color
case Text case Text
case Size
case LineWidth
case FillOpacity
case FillOutlineColor
} }
enum IconImage: String, CaseIterable { enum DataType : String {
case OwnShip_Alarm case ownShip
case OwnShip_Caution case point
case OwnShip_Emergency case line
case OwnShip_NeCST_Emergency case add
case OwnShip_Normal }
case OwnShip_Offline
case OwnShip_Unknown /**
case OwnShip_Warning * 地図上クリック
case SwNoticeBack */
case SwStartBack func mapClick(point: CGPoint, coordinate: CLLocationCoordinate2D) {
case SwFinisheBack let layers = [
ownShipSymbol.layerId,
editAreaSymbol.layerId,
editAreaAddSymbol.layerId
]
self.touchedFeatures = nil
var features : [Feature] = []
let option = RenderedQueryOptions(layerIds: layers, filter: nil)
mapView.mapboxMap.queryRenderedFeatures(with: point, options: option) { [self] result in
switch result {
case .success(let queriedFeature):
for feature in queriedFeature {
features.append(feature.feature)
}
if let feature = features.last {
self.touchedFeatures = feature
}
clickSymbolLayer(tatchPoint: point, coordinate: coordinate)
case .failure(let error):
print(error.localizedDescription)
}
}
} }
}
/**
* ポイントクリック処理
*/
private func clickSymbolLayer(tatchPoint: CGPoint, coordinate: CLLocationCoordinate2D) {
if let targetFeature = self.touchedFeatures {
print(debug: "Test: clickSymbolLayer \(coordinate)")
guard let type = targetFeature.properties?[PropertyKey.Dtype.rawValue] else {return}
switch type! {
case Turf.JSONValue.string(DataType.point.rawValue):
guard let jsonData = targetFeature.properties?[PropertyKey.Id.rawValue] else {return}
guard let Id = jsonData?.rawValue else {return}
if let noStr = Id as? String {
if let no = Int(noStr) {
SharingData.nga.selectPoint = no
}
}
if SharingData.nga.editNga?.isLock == false {
SharingData.nga.editType = EditNgaType.movePoint
SharingData.nga.moveNga = SharingData.nga.editNga
lockEditPoint(isLocked: false) //地図を固定
updateEditTargetSymbol(point: coordinate)
}
case Turf.JSONValue.string(DataType.add.rawValue):
print(debug: "Test: clickSymbolLayer(add) \(coordinate)")
guard let jsonData = targetFeature.properties?[PropertyKey.Id.rawValue] else {return}
guard let Id = jsonData?.rawValue else {return}
if SharingData.nga.editNga?.isLock == false {
if let noStr = Id as? String {
if let no = Int(noStr) {
SharingData.nga.editNga?.points.insert(coordinate, at: no)
}
}
}
default:
if SharingData.nga.editType == EditNgaType.addPoint {
if let editNga = SharingData.nga.editNga {
if editNga.points.count < ngaAreaPointMax {
SharingData.nga.editNga?.points.append(coordinate)
}
}
}
}
} else {
if SharingData.nga.editType == EditNgaType.addPoint {
if let editNga = SharingData.nga.editNga {
if editNga.points.count < ngaAreaPointMax {
SharingData.nga.editNga?.points.append(coordinate)
}
}
}
if SharingData.nga.editType == EditNgaType.movePoint {
SharingData.nga.editType = EditNgaType.addPoint
SharingData.map.isMapFree = true
}
}
}
/**
* 地図上ロングクリック
*/
func mapLongClick(point: CGPoint, coordinate: CLLocationCoordinate2D) {
let layers = [
editAreaSymbol.layerId
]
self.touchedFeatures = nil
var features : [Feature] = []
let option = RenderedQueryOptions(layerIds: layers, filter: nil)
mapView.mapboxMap.queryRenderedFeatures(with: point, options: option) { [self] result in
switch result {
case .success(let queriedFeature):
for feature in queriedFeature {
features.append(feature.feature)
}
if let feature = features.last {
self.touchedFeatures = feature
}
longClickSymbolLayer(tatchPoint: point, coordinate: coordinate)
case .failure(let error):
print(error.localizedDescription)
}
}
}
/**
* ポイント削除
*/
private func longClickSymbolLayer(tatchPoint: CGPoint, coordinate: CLLocationCoordinate2D) {
if SharingData.nga.editType == EditNgaType.addPoint {
if let targetFeature = self.touchedFeatures {
print(debug: "Test: longClickSymbolLayer \(coordinate)")
guard let type = targetFeature.properties?[PropertyKey.Dtype.rawValue] else {return}
if type! == Turf.JSONValue.string(DataType.point.rawValue) {
guard let jsonData = targetFeature.properties?[PropertyKey.Id.rawValue] else {return}
guard let Id = jsonData?.rawValue else {return}
if let noStr = Id as? String {
if let no = Int(noStr) {
SharingData.nga.editType = EditNgaType.deletePoint
SharingData.nga.selectPoint = no
}
}
}
updateEditArea()
}
}
}
/**
* 地図上ドラッグ
*/
private func mapDrug(point: CGPoint, coordinate: CLLocationCoordinate2D) {
let layers = [
editAreaSymbol.layerId
]
self.touchedFeatures = nil
var features : [Feature] = []
let option = RenderedQueryOptions(layerIds: layers, filter: nil)
print(debug: "Test: (Drug) \(coordinate)")
mapView.mapboxMap.queryRenderedFeatures(with: point, options: option) { [self] result in
switch result {
case .success(let queriedFeature):
for feature in queriedFeature {
features.append(feature.feature)
}
if let feature = features.last {
self.touchedFeatures = feature
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
/**
* ポイントの選択状態の設定
* setUserMarkRock
*/
func lockEditPoint(isLocked: Bool){
let drug = UIPanGestureRecognizer(target: self, action: #selector(handleMapDrug))
if isLocked {
mapView.removeGestureRecognizer(drug)
for recognizer in mapView.gestureRecognizers!where recognizer is UIPanGestureRecognizer {
recognizer.isEnabled = true
}
} else {
for recognizer in mapView.gestureRecognizers!where recognizer is UIPanGestureRecognizer {
recognizer.isEnabled = false
drug.require(toFail: recognizer)
}
mapView.addGestureRecognizer(drug)
}
}
}
...@@ -13,7 +13,7 @@ struct MapSource { ...@@ -13,7 +13,7 @@ struct MapSource {
let layerId : String let layerId : String
var source = GeoJSONSource() var source = GeoJSONSource()
init(layer : LayerEnum){ init(layer : MapViewController.LayerEnum) {
sourceId = layer.rawValue + "Source" sourceId = layer.rawValue + "Source"
layerId = layer.rawValue + "Layer" layerId = layer.rawValue + "Layer"
} }
......
...@@ -26,9 +26,9 @@ struct EcaListView: View { ...@@ -26,9 +26,9 @@ struct EcaListView: View {
var newData = eca var newData = eca
newData.isEnable.toggle() newData.isEnable.toggle()
ecaData.editEcaArea(key: eca.areaId, value: newData, type: EcaOperation.Insert) ecaData.editEcaArea(key: eca.areaId, value: newData, type: EcaOperation.Insert)
taskViewModel.viewMode = .SwitchingMenu taskViewModel.viewMode = .FuelSwitching
taskViewModel.edittingEcaArea = eca taskViewModel.edittingEcaArea = eca
taskViewModel.isShowSettingView = true taskViewModel.viewMode = .EcaSetting
}, label: { }, label: {
Image("icon_plus") Image("icon_plus")
.resizable() .resizable()
......
...@@ -9,8 +9,7 @@ import SwiftUI ...@@ -9,8 +9,7 @@ import SwiftUI
import UIKit import UIKit
struct EcaSettingView: View { struct EcaSettingView: View {
// @ObservedObject var taskViewModel: TaskViewModel @ObservedObject var taskViewModel: TaskViewModel
@Binding var isShowSettingEca: Bool
@State var edittingEca: RegisteredEca @State var edittingEca: RegisteredEca
var body: some View { var body: some View {
...@@ -40,7 +39,6 @@ struct EcaSettingView: View { ...@@ -40,7 +39,6 @@ struct EcaSettingView: View {
var ecaData = edittingEca var ecaData = edittingEca
ecaData.isEnable = true ecaData.isEnable = true
SharingData.eca.editEcaArea(key: edittingEca.areaId, value: ecaData, type: EcaOperation.Change) SharingData.eca.editEcaArea(key: edittingEca.areaId, value: ecaData, type: EcaOperation.Change)
isShowSettingEca = false
}, label: { }, label: {
Text("Register") Text("Register")
.font(FontStyle.DefaultText.font) .font(FontStyle.DefaultText.font)
...@@ -213,5 +211,5 @@ struct EcaSettingView: View { ...@@ -213,5 +211,5 @@ struct EcaSettingView: View {
} }
#Preview { #Preview {
EcaSettingView(isShowSettingEca: .constant(true), edittingEca: RegisteredEca(id: 0, ecaName: "eca")!) EcaSettingView(taskViewModel: TaskViewModel(), edittingEca: RegisteredEca(id: 0, areaName: "Alert Area")!)
} }
// //
// TaskSwitchingMenuView.swift // FuelSwitchingView.swift
// forShip // forShip
// //
// Created by Mamoru Sugita on 2023/10/18. // Created by Mamoru Sugita on 2023/10/18.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import SwiftUI import SwiftUI
struct TaskSwitchingMenuView: View { struct FuelSwitchingView: View {
@ObservedObject var taskViewModel: TaskViewModel @ObservedObject var taskViewModel: TaskViewModel
@ObservedObject var ecaData = SharingData.eca @ObservedObject var ecaData = SharingData.eca
@State var isDeleteAlert: Bool = false @State var isDeleteAlert: Bool = false
...@@ -57,7 +57,7 @@ struct TaskSwitchingMenuView: View { ...@@ -57,7 +57,7 @@ struct TaskSwitchingMenuView: View {
Button{ Button{
taskViewModel.edittingEcaArea = eca taskViewModel.edittingEcaArea = eca
taskViewModel.ecaName = eca.name taskViewModel.ecaName = eca.name
taskViewModel.isShowSettingView = true taskViewModel.viewMode = .EcaSetting
} label: { } label: {
Text("Edit Notice Setting") Text("Edit Notice Setting")
} }
...@@ -102,15 +102,6 @@ struct TaskSwitchingMenuView: View { ...@@ -102,15 +102,6 @@ struct TaskSwitchingMenuView: View {
taskViewModel.edittingEcaArea = nil taskViewModel.edittingEcaArea = nil
} }
Button("No"){} Button("No"){}
// Button("Cancel"){¥
// if let ecaArea = taskViewModel.edittingEcaArea {
// var newData = ecaArea
// newData.isRunning = false
// newData.status = EcaState.cancel
// ecaData.editEcaArea(key: ecaArea.name, value: newData, type: EcaOperation.Cancel)
// }
// taskViewModel.edittingEcaArea = nil
// }
} message: { } message: {
Text("Have you finished " + taskViewModel.ecaName + " fuel switching?") Text("Have you finished " + taskViewModel.ecaName + " fuel switching?")
} }
...@@ -137,11 +128,10 @@ struct TaskSwitchingMenuView: View { ...@@ -137,11 +128,10 @@ struct TaskSwitchingMenuView: View {
Spacer() Spacer()
} }
// .padding()
} }
} }
#Preview { #Preview {
TaskSwitchingMenuView(taskViewModel: TaskViewModel()) FuelSwitchingView(taskViewModel: TaskViewModel())
} }
//
// MapTaskView.swift
// forShip
//
// Created by Mamoru Sugita on 2023/10/17.
//
import SwiftUI
enum TaskViewMode{
case SwitchingMenu
case EcaList
var title: String{
switch self{
case .SwitchingMenu:
"Fuel Switching"
case .EcaList:
"ECA List"
}
}
}
struct MapTaskView: View {
@ObservedObject var taskViewModel = TaskViewModel()
@ObservedObject var eca = SharingData.eca
var body: some View {
VStack{
if UIDevice.current.userInterfaceIdiom == .phone {
Capsule()
.foregroundColor(ColorSet.ScrollBarColor.color)
.frame(width: 45, height: 3)
.padding(.top, 10)
}
//タイトルエリア
HStack{
Button(action: {
taskViewModel.viewMode = .SwitchingMenu
taskViewModel.isShowSettingView = false
}, label: {
if taskViewModel.viewMode != .SwitchingMenu || taskViewModel.isShowSettingView{
Image("ink_02")
}
})
.frame(width: 48, height: 48)
Spacer()
Text(taskViewModel.isShowSettingView ? taskViewModel.edittingEcaArea?.name ?? "" : taskViewModel.viewMode.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
Button(action: {
}, label: {
})
.frame(width: 48, height: 48)
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
ScrollViewReader { proxy in
ScrollView(.vertical){
switch taskViewModel.viewMode {
case .SwitchingMenu:
if let edittingEcaArea = taskViewModel.edittingEcaArea, taskViewModel.isShowSettingView{
EcaSettingView(isShowSettingEca: $taskViewModel.isShowSettingView, edittingEca: edittingEcaArea)
}else{
TaskSwitchingMenuView(taskViewModel: taskViewModel)
}
case .EcaList:
EcaListView(taskViewModel: taskViewModel)
}
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
// proxy.scrollTo("scroll", anchor: .top)
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
.onAppear{
let appVersionModel = AppVersionModel()
appVersionModel.start()
}
.alert("", isPresented: $eca.isShowEcaAlert) {
// if let ecaArea = eca.ecaArea.map({ $0.1 }).filter({ $0.isRunning }).first{
Button("OK"){
// let ecaTask = EcaTask()
// ecaTask.chengeEcaStatus(eca: ecaArea)
// if let status = SharingData.my.ecaStatus {
// if status == .finishPass {
// var newData = ecaArea
// newData.isRunning = false
// newData.status = EcaState.incomplete
// SharingData.eca.editEcaArea(key: ecaArea.name, value: newData, type: EcaOperation.Incomplete)
// }
// }
}
// }
} message: {
if let ecaArea = eca.ecaArea.map({ $0.1 }).filter({ $0.isRunning }).first{
if let status = SharingData.my.ecaStatus {
switch status {
case .noticePass:
Text("Arrived at advance notice point.")
case .startPass:
Text("Arrived at switching start point.")
case .finishPass:
Text("Have you finished \(ecaArea.name) fuel switching?\nIf you finish, you disable it.")
case .incomplete:
Text("Have you finished \(ecaArea.name) fuel switching?\nIf you finish, you disable it.")
default:
Text("")
}
}
}
}
}
}
#Preview {
MapTaskView()
}
//
// MenuTaskView.swift
// forShip
//
// Created by Mamoru Sugita on 2023/10/17.
//
import SwiftUI
enum TaskViewMode {
case MenuList
case FuelSwitching
case EcaList
case EcaSetting
case NgaNotification
case NgaSetting
var title: String {
switch self {
case .MenuList:
"Menu Functions"
case .FuelSwitching:
"Fuel Switching"
case .EcaList:
"ECA List"
case .EcaSetting:
"ECA Setting"
case .NgaNotification:
"NGA Notification"
case .NgaSetting:
"NGA Setting"
}
}
}
struct MenuTaskView: View {
@ObservedObject var taskViewModel = TaskViewModel()
@ObservedObject var eca = SharingData.eca
@ObservedObject var nga = SharingData.nga
var body: some View {
VStack{
if UIDevice.current.userInterfaceIdiom == .phone {
Capsule()
.foregroundColor(ColorSet.ScrollBarColor.color)
.frame(width: 45, height: 3)
.padding(.top, 10)
}
switch taskViewModel.viewMode {
case .MenuList:
MenuMain(taskViewModel: taskViewModel)
case .FuelSwitching:
FuelSwitchingMain(taskViewModel: taskViewModel)
case .EcaList:
EcaListMain(taskViewModel: taskViewModel)
case .EcaSetting:
EcaSettingMain(taskViewModel: taskViewModel)
case .NgaNotification:
NgaNotificationMain(taskViewModel: taskViewModel)
case .NgaSetting:
NgaSettingMain(taskViewModel: taskViewModel)
}
}
.onAppear{
let appVersionModel = AppVersionModel()
appVersionModel.start()
nga.editType = EditNgaType.registered
}
.alert("", isPresented: $eca.isShowEcaAlert) {
// if let ecaArea = eca.ecaArea.map({ $0.1 }).filter({ $0.isRunning }).first{
Button("OK"){
// let ecaTask = EcaTask()
// ecaTask.chengeEcaStatus(eca: ecaArea)
// if let status = SharingData.my.ecaStatus {
// if status == .finishPass {
// var newData = ecaArea
// newData.isRunning = false
// newData.status = EcaState.incomplete
// SharingData.eca.editEcaArea(key: ecaArea.name, value: newData, type: EcaOperation.Incomplete)
// }
// }
}
// }
} message: {
if let ecaArea = eca.ecaArea.map({ $0.1 }).filter({ $0.isRunning }).first{
if let status = SharingData.my.ecaStatus {
switch status {
case .noticePass:
Text("Arrived at advance notice point.")
case .startPass:
Text("Arrived at switching start point.")
case .finishPass:
Text("Have you finished \(ecaArea.name) fuel switching?\nIf you finish, you disable it.")
case .incomplete:
Text("Have you finished \(ecaArea.name) fuel switching?\nIf you finish, you disable it.")
default:
Text("")
}
}
}
}
}
}
/**
* Menu画面
*/
struct MenuMain: View {
@ObservedObject var taskViewModel = TaskViewModel()
var body: some View {
//タイトルエリア
HStack{
Spacer()
Text(TaskViewMode.MenuList.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
ScrollViewReader { proxy in
ScrollView(.vertical){
Button(action: {
taskViewModel.viewMode = .FuelSwitching
}, label: {
Text(TaskViewMode.FuelSwitching.title)
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
Button(action: {
taskViewModel.viewMode = .NgaNotification
}, label: {
Text(TaskViewMode.NgaNotification.title)
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
}
/**
* Fuel Switching画面
*/
struct FuelSwitchingMain: View {
@ObservedObject var taskViewModel = TaskViewModel()
var body: some View {
//タイトルエリア
HStack{
Button(action: {
taskViewModel.viewMode = .MenuList
}, label: {
Image("ink_02")
})
.frame(width: 48, height: 48)
Spacer()
Text(TaskViewMode.FuelSwitching.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
Button(action: {
}, label: {
})
.frame(width: 48, height: 48)
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
//ECAリスト
ScrollViewReader { proxy in
ScrollView(.vertical){
FuelSwitchingView(taskViewModel: taskViewModel)
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
}
/**
* ECA List画面
*/
struct EcaListMain: View {
@ObservedObject var taskViewModel = TaskViewModel()
var body: some View {
//タイトルエリア
HStack{
Button(action: {
taskViewModel.viewMode = .FuelSwitching
}, label: {
Image("ink_02")
})
.frame(width: 48, height: 48)
Spacer()
Text(TaskViewMode.EcaList.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
Button(action: {
}, label: {
})
.frame(width: 48, height: 48)
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
ScrollViewReader { proxy in
ScrollView(.vertical){
EcaListView(taskViewModel: taskViewModel)
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
}
/**
* ECA Setting画面
*/
struct EcaSettingMain: View {
@ObservedObject var taskViewModel = TaskViewModel()
var body: some View {
//タイトルエリア
HStack{
Button(action: {
taskViewModel.viewMode = .FuelSwitching
}, label: {
Image("ink_02")
})
.frame(width: 48, height: 48)
Spacer()
Text(TaskViewMode.EcaSetting.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
Button(action: {
}, label: {
})
.frame(width: 48, height: 48)
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
ScrollViewReader { proxy in
ScrollView(.vertical){
if let edittingEcaArea = taskViewModel.edittingEcaArea {
EcaSettingView(taskViewModel: taskViewModel, edittingEca: edittingEcaArea)
}
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
}
/**
* NGA Notification画面
*/
struct NgaNotificationMain: View {
@ObservedObject var taskViewModel = TaskViewModel()
var body: some View {
//タイトルエリア
HStack{
Button(action: {
taskViewModel.viewMode = .MenuList
}, label: {
Image("ink_02")
})
.frame(width: 48, height: 48)
Spacer()
Text(TaskViewMode.NgaNotification.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
Button(action: {
}, label: {
})
.frame(width: 48, height: 48)
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
ScrollViewReader { proxy in
ScrollView(.vertical){
NgaNotificationView(taskViewModel: taskViewModel)
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
}
/**
* NGA設定画面
*/
struct NgaSettingMain: View {
@ObservedObject var taskViewModel = TaskViewModel()
@ObservedObject var nga = SharingData.nga
@ObservedObject var map = SharingData.map
var body: some View {
//タイトルエリア
HStack{
Button(action: {
if taskViewModel.viewMode == .NgaSetting && nga.editType == EditNgaType.movePoint {
nga.editNga = nga.moveNga
nga.editType = EditNgaType.addPoint
map.isMapFree = true
} else {
taskViewModel.viewMode = .NgaNotification
nga.editType = EditNgaType.registered
}
}, label: {
Image("ink_02")
})
.frame(width: 48, height: 48)
Spacer()
Text(TaskViewMode.NgaSetting.title)
.font(FontStyle.TitleL.font)
.frame(height: 20)
.padding(.vertical, 14)
Spacer()
Button(action: {
}, label: {
})
.frame(width: 48, height: 48)
}
.padding(EdgeInsets(top: 10, leading: 8, bottom: 13, trailing: 17))
Divider()
.background(ColorSet.LineColor03.color)
ScrollViewReader { proxy in
ScrollView(.vertical){
NgaSettingView(taskViewModel: taskViewModel)
}
.onChange(of: taskViewModel.viewMode){ newViewMode in
proxy.scrollTo(0, anchor: .top)
}
}
Spacer()
.frame(height: 55)
}
}
#Preview {
MenuTaskView()
}
#Preview {
MenuMain(taskViewModel: TaskViewModel())
}
#Preview {
FuelSwitchingMain(taskViewModel: TaskViewModel())
}
#Preview {
EcaListMain(taskViewModel: TaskViewModel())
}
#Preview {
EcaSettingMain(taskViewModel: TaskViewModel())
}
#Preview {
NgaNotificationMain(taskViewModel: TaskViewModel())
}
#Preview {
NgaSettingMain(taskViewModel: TaskViewModel())
}
//
// NgaNotificationView.swift
// forShip
//
// Created by Mamoru Sugita on 2023/10/18.
//
import SwiftUI
struct NgaNotificationView: View {
@ObservedObject var taskViewModel: TaskViewModel
@ObservedObject var ngaData = SharingData.nga
@State var isDelete: Bool = false
@State var isRunningStopNga: Bool = false
var body: some View {
VStack {
// ForEach(ngaData.ngaArea.map{ $0.1 }.sorted{ $0.name < $1.name }, id: \.areaId) { nga in
ForEach(ngaData.ngaArea.map{ $0.1 }, id: \.areaId) { nga in
VStack {
HStack {
//NGA開始・終了ボタン
Button {
var newData = nga
newData.isRunning.toggle()
newData.passingCnt = 0
if newData.isRunning {
ngaData.editNgaArea(value: newData, type: NgaOperation.Running)
} else {
ngaData.editNgaArea(value: newData, type: NgaOperation.Cancel)
}
} label: {
HStack {
Circle()
.frame(width: 14, height: 14)
.foregroundColor(nga.isRunning ? ColorSet.PrimaryActiveIcon.color : ColorSet.TaskStateIcon.color)
Spacer()
.frame(width: 10)
}
}
//NGA移動
Text(nga.name)
.font(FontStyle.DefaultText.font)
.foregroundColor(ColorSet.Body.color)
.onTapGesture {
ngaData.focusNga = nga.areaId.uuidString
}
Spacer()
Menu {
Text(nga.name)
Button{
ngaData.editNga = nga
taskViewModel.viewMode = .NgaSetting
ngaData.editType = EditNgaType.nonEdit
} label: {
Text("Edit Nga Setting")
}
//削除
Button{
ngaData.editNga = nga
isDelete = true
} label: {
Text("Delete NGA Notification")
}.disabled(nga.isLock)
} label: {
Image(systemName: "ellipsis")
.frame(width: 22, height: 22)
.foregroundColor(nga.isRunning ? ColorSet.Splash.color : ColorSet.Slidebar.color)
}
.disabled(nga.isRunning)
.alert("Delete", isPresented: $isDelete) {
Button("Yes") {
if let newData = ngaData.editNga {
ngaData.editNgaArea(value: newData, type: NgaOperation.Delete)
ngaData.editNga = nil
}
}
Button("No"){}
} message: {
Text("Delete " + nga.name + " ?")
}
.alert("NGA Switching", isPresented:$isRunningStopNga) {
Button("Yes") {
var newData = nga
newData.isRunning = false
ngaData.editNgaArea(value: newData, type: NgaOperation.Cancel)
}
Button("No"){}
} message: {
Text("Have you finished " + nga.name + "switching?")
}
}
.frame(height: 60)
.padding(.horizontal, 30)
Divider()
.background(.white)
}
}
//Add NGAボタン
let isAddNga = ngaData.ngaArea.count < ngaAreaMax
Button(action: {
if var ngaTmp = RegisteredNga(areaName: "") {
ngaTmp.isLock = false
ngaTmp.isRunning = false
ngaTmp.name = "NGA Area" + String(ngaData.ngaArea.count)
ngaData.editType = EditNgaType.nonEdit
ngaData.editNga = ngaTmp
taskViewModel.viewMode = .NgaSetting
}
}, label: {
Text("Add NGA Task")
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(!isAddNga ? ColorSet.SecondaryDisable.color : ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
.disabled(!isAddNga)
Spacer()
}
}
}
#Preview {
NgaNotificationView(taskViewModel: TaskViewModel())
}
//
// NgaSettingView.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/05/21.
//
import SwiftUI
import CoreLocation
import UIKit
struct NgaSettingView: View {
@ObservedObject var taskViewModel: TaskViewModel
@ObservedObject var nga = SharingData.nga
@ObservedObject var map = SharingData.map
var body: some View {
if nga.editType == EditNgaType.movePoint {
NgaPointSetting(taskViewModel: taskViewModel)
} else {
NgaSetting(taskViewModel: taskViewModel)
}
}
}
struct NgaSetting: View {
@ObservedObject var taskViewModel: TaskViewModel
@ObservedObject var nga = SharingData.nga
@ObservedObject var map = SharingData.map
var body: some View {
VStack(spacing: 0) {
HStack {
Text("Area Name").padding(.horizontal, 0)
.foregroundColor(nga.editNga!.isLock ? ColorSet.BodyDescriptiion.color : ColorSet.Body.color)
TextField("", text: $taskViewModel.ngaName)
.foregroundColor(nga.editNga!.isLock ? ColorSet.BodyDescriptiion.color : ColorSet.Body.color)
.textFieldStyle(RoundedBorderTextFieldStyle())
.keyboardType(.emailAddress)
.frame(width: 150)
.disabled(nga.editNga!.isLock)
let stateLock = nga.editNga!.points.count < 3 || nga.editNga!.name.isEmpty
Button{
if var ngaData = nga.editNga {
ngaData.isLock.toggle()
nga.editNga = ngaData
nga.editType = EditNgaType.nonEdit
}
}label:{
if nga.editNga!.isLock {
Image(systemName: "lock.fill")
.foregroundColor(Color.white)
.scaledToFit()
.frame(height: 18)
} else {
Image(systemName: "lock.open.fill")
.foregroundColor(stateLock ? ColorSet.BodyDescriptiion.color : ColorSet.Body.color)
.scaledToFit()
.frame(height: 18)
}
}
.disabled(stateLock)
.padding(.horizontal, 30)
}
.onAppear(perform: {
if let name = nga.editNga?.name {
taskViewModel.ngaName = name
}
})
// HStack {
// Button{
// var ngaData = nga.editNga!
// ngaData.isRunning.toggle()
// ngaData.passingCnt = 0
// nga.editNga = ngaData
// }label:{
// HStack {
// Text("Watch")
// .font(FontStyle.EmphasisText.font)
// .foregroundColor(nga.editNga!.isLock ? ColorSet.BodyDescriptiion.color : ColorSet.Body.color)
//
// if nga.editNga!.isRunning {
// Image(systemName: "checkmark.square.fill")
// .resizable()
// .frame(width: 22, height: 22)
// } else {
// Image(systemName: "square")
// .resizable()
// .frame(width: 22, height: 22)
// }
// }
// .padding(.vertical, 17)
// .padding(.horizontal, 30)
// }
// .disabled(nga.editNga!.isLock)
//
// Button{
// var ngaData = nga.editNga!
// ngaData.isLock.toggle()
// nga.editNga = ngaData
// }label:{
// HStack {
// Text("Lock")
// .font(FontStyle.EmphasisText.font)
// .foregroundColor(ColorSet.Body.color)
//
// if nga.editNga!.isLock {
// Image(systemName: "checkmark.square.fill")
// .resizable()
// .frame(width: 22, height: 22)
// } else {
// Image(systemName: "square")
// .resizable()
// .frame(width: 22, height: 22)
// }
// }
// .padding(.horizontal, 30)
// }
// }
HStack {
let stateEdit = nga.editNga!.isLock ? true : nga.editType != EditNgaType.nonEdit
Button(action: {
nga.editType = EditNgaType.addPoint
}, label: {
Text("Edit polygon")
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(stateEdit ? ColorSet.SecondaryDisable.color : ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
.padding(.vertical, 20)
.disabled(stateEdit)
let stateRegister = nga.editNga!.points.count < 3 || nga.editNga!.name.isEmpty
Button(action: {
if var ngaData = nga.editNga {
ngaData.name = taskViewModel.ngaName
nga.editType = EditNgaType.registered
nga.editNgaArea(value: ngaData, type: NgaOperation.Change)
}
taskViewModel.viewMode = .NgaNotification
}, label: {
Text("Register")
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(stateRegister ? ColorSet.SecondaryDisable.color : ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
.padding(.vertical, 20)
.disabled(stateRegister)
}
}
}
}
/**
* ポイント位置移動
*/
struct NgaPointSetting: View {
@ObservedObject var taskViewModel: TaskViewModel
@State private var selectLat = Array(repeating: 0, count: 4)
@State private var selectLon = Array(repeating: 0, count: 4)
var body: some View {
ZStack {
VStack(spacing: 0) {
HStack {
Picker("", selection: $selectLat[0]) {
Text("N")
Text("S")
}.pickerStyle(.wheel)
Picker("", selection: $selectLat[1]) {
ForEach((0...89), id:\.self) { num in
Text("\(num)")
}
}.pickerStyle(.wheel)
Text("°").padding(.horizontal, 0)
Picker("", selection: $selectLat[2]) {
ForEach((0...59), id:\.self) { num in
Text("\(num)")
}
}.pickerStyle(.wheel)
Text(".").padding(.horizontal, 0)
Picker("", selection: $selectLat[3]) {
ForEach((0...999), id:\.self) { num in
Text("\(num)")
}
}.pickerStyle(.wheel)
Text("'").padding(.horizontal, 0)
}
.frame(width: 350, height: 60)
.onChange(of: selectLat) { value in
changeLocationDouble()
}
HStack {
Picker("", selection: $selectLon[0]) {
Text("E")
Text("W")
}.pickerStyle(.wheel)
Picker("", selection: $selectLon[1]) {
ForEach((0...179), id:\.self) { num in
Text("\(num)")
}
}.pickerStyle(.wheel)
Text("°").padding(.horizontal, 0)
Picker("", selection: $selectLon[2]) {
ForEach((0...59), id:\.self) { num in
Text("\(num)")
}
}.pickerStyle(.wheel)
Text(".").padding(.horizontal, 0)
Picker("", selection: $selectLon[3]) {
ForEach((0...999), id:\.self) { num in
Text("\(num)")
}
}.pickerStyle(.wheel)
Text("'").padding(.horizontal, 0)
}
.frame(width: 350, height: 60)
.onChange(of: selectLon) { value in
changeLocationDouble()
}
HStack {
Button(action: {
SharingData.nga.editType = EditNgaType.deletePoint
}, label: {
Text("Delete")
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
.padding(.vertical, 20)
Button(action: {
SharingData.nga.editType = EditNgaType.addPoint
}, label: {
Text("Set")
.font(FontStyle.DefaultText.font)
.padding()
})
.frame(width: 153, height: 42)
.foregroundColor(ColorSet.ButtonText.color)
.background(ColorSet.PrimaryActiveIcon.color)
.cornerRadius(30)
.padding(.vertical, 20)
}
}
}
.onAppear(perform: {
changeLocationArray()
})
.onChange(of: selectLat) { newValue in
changeLocationDouble()
}
}
/**
* Picker情報用に位置情報を分解
*/
func changeLocationArray() {
if let no = SharingData.nga.selectPoint {
if let location = SharingData.nga.editNga?.points[no] {
selectLat = LocationCalculation.latDegtoInt(lat: location.latitude)
selectLon = LocationCalculation.lonDegtoInt(lon: location.longitude)
}
}
}
/**
* Picker情報から位置情報に変換
*/
func changeLocationDouble() {
if let no = SharingData.nga.selectPoint {
var location = SharingData.nga.editNga!.points[no]
location.latitude = LocationCalculation.latInttoDouble(lat: selectLat)!
location.longitude = LocationCalculation.lonInttoDouble(lon: selectLon)!
SharingData.nga.editNga!.points[no] = location
SharingData.nga.targetLocation = location
}
}
}
#Preview {
NgaSettingView(taskViewModel: TaskViewModel())
}
#Preview {
NgaSetting(taskViewModel: TaskViewModel())
}
#Preview {
NgaPointSetting(taskViewModel: TaskViewModel())
}
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
import Foundation import Foundation
class TaskViewModel: ObservableObject{ class TaskViewModel: ObservableObject{
@Published var viewMode: TaskViewMode = .SwitchingMenu @Published var viewMode: TaskViewMode = .MenuList
@Published var edittingEcaArea: RegisteredEca? = nil @Published var edittingEcaArea: RegisteredEca? = nil
@Published var ecaName: String = "" @Published var ecaName: String = ""
@Published var isShowSettingView : Bool = false @Published var ngaName: String = ""
} }
...@@ -10,7 +10,7 @@ import SwiftUI ...@@ -10,7 +10,7 @@ import SwiftUI
struct MenuTitleView: View { struct MenuTitleView: View {
@Binding var path : [MenuPath] @Binding var path : [MenuPath]
var title = "Menu" var title = "Menu Functions"
var body: some View { var body: some View {
VStack { VStack {
HStack{ HStack{
......
//
// DeleteNgaArea.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/05/20.
//
import Foundation
class DeleteNgaArea {
var sessionNgaList = SessionNgaList()
func start(areaId : String) {
print(debug: "called")
sessionNgaList.RequestDeleteNgaList(areaId, completion: responseDeleteNgaList)
}
private func responseDeleteNgaList(result: Result<Data, APIError>) {
print(debug: "called")
switch result {
case .success(let resultData):
print(debug: resultData)
case .failure(let errorCode):
print(debug: errorCode)
break
}
}
}
//
// GetNgaList.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/06/15.
//
import Foundation
import SwiftUI
import CoreLocation
class GetNgaList {
@ObservedObject var ngaData = SharingData.nga
var sessionNgaList = SessionNgaList()
func start() {
print(debug: "called")
sessionNgaList.RequestGetNgaList(responseGetNgaList)
}
private func responseGetNgaList(result: Result<Data, APIError>) {
print(debug: "called")
print(debug: "Test: GetNgaList")
switch result {
case .success(let resultData):
let serverSession = ServerSession()
let resjson = serverSession.fromJSON(resultData: resultData, resltType: [ReqNgaList].self)
if let res = resjson {
var ngaAreas = ngaData.ngaArea
for ngaList in res {
if let id = NSUUID(uuidString: ngaList.id) {
if var nga = ngaAreas[id as UUID] {
print(debug: "Test: 1\(nga)")
// nga.name = ngaList.name
nga.isLock = ngaList.lock
nga.points.removeAll()
for pos in ngaList.geometry{
let point = CLLocationCoordinate2D(latitude: pos.lat!, longitude: pos.lon!)
nga.points.append(point)
}
ngaAreas.updateValue(nga, forKey: nga.areaId)
print(debug: "Test: 2\(nga)")
} else {
if var nga = RegisteredNga(areaName: "test dammy") { //TODO: 名称はダミー
nga.areaId = id as UUID
nga.isLock = ngaList.lock
nga.isRunning = ngaList.enabled
if !ngaList.enabled {
nga.passingCnt = 0
}
nga.color = Color.green.description
for pos in ngaList.geometry{
let point = CLLocationCoordinate2D(latitude: pos.lat!, longitude: pos.lon!)
nga.points.append(point)
}
ngaAreas.updateValue(nga, forKey: nga.areaId)
}
}
}
for ares in ngaAreas {
ngaData.setNgaArea(key: ares.value.areaId, value: ares.value)
}
}
}
case .failure(let errorCode):
print(debug: errorCode)
break
}
}
}
//
// NgaTask.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/06/11.
//
import Foundation
class NgaTask {
var ngaData = SharingData.nga
/**
* Nga通知
*/
private func notificationNga(point: SwitchingAlert, name: String) {
let alertDB = AlertDB.OnlyOne
var wernrec = WarnRecord(title:"Nga", body:"")
wernrec = alertDB.GetAlertNgaPoint(point: point)
let formatstr = wernrec.title + name
wernrec.title = String(format: formatstr)
let voicemanager = AlertManager.OnlyOne
voicemanager.VocalizeAlert(alertrec: wernrec, identifier: .NgaAlert)
}
func checkNga() {
ngaData.ngaArea.forEach { nga in
if nga.value.isRunning {
if let location = SharingData.location.location {
var shipPos = LocationCalculation.AreaLatLon()
shipPos.NorthLat = location.latitude
shipPos.SouthLat = location.latitude
shipPos.EastLon = location.longitude
shipPos.WestLon = location.longitude
var areaPoints = nga.value.points
areaPoints.append(nga.value.points[0])
let isInside = LocationCalculation.checkBeset(objPos: areaPoints, minMax: shipPos, exceed180: false)
var area = nga.value
if isInside {
//通過中
area.passingCnt += 1
let test = area.passingCnt
print(debug: "Test: \(test)")
ngaData.editNgaArea(value: area, type: NgaOperation.Passing)
if area.passingCnt == 1 {
let areaName = nga.value.name
notificationNga(point: SwitchingAlert.NgaPassing, name: areaName)
}
} else {
if area.passingCnt > 0 {
//通過
area.passingCnt = 0
ngaData.editNgaArea(value: area, type: NgaOperation.Passing)
}
}
}
}
}
}
}
//
// RegistereNga.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/05/16.
//
import Foundation
import CoreLocation
import SwiftUI
let ngaAreaMax = 30
let ngaAreaPointMax = 50
enum EditNgaType {
case nonEdit
case addPoint
case movePoint
case deletePoint
case registered
}
struct RegisteredNga {
var areaId = UUID()
var isLock: Bool = false
var isRunning: Bool = false
var passingCnt: Int = 0 //1以上で通過中
var name: String = "" //Area名称
var datetime: String = "" //時刻(UTC ISO8601準拠)
var color = Color.green.description //ライン色(ARGB)
var width: Int = 1 //ライン幅
var points: [CLLocationCoordinate2D] = []
init?(areaName: String ) {
self.name = areaName
}
}
//
// SetNgaArea.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/06/14.
//
import Foundation
import SwiftUI
class SetNgaArea {
@ObservedObject var ngaData = SharingData.nga
var sessionNgaList = SessionNgaList()
func start(nga : ReqNgaList) {
print(debug: "called")
sessionNgaList.RequestPostNgaList(nga, completion: responsePostNgaList)
}
private func responsePostNgaList(result: Result<Data, APIError>) {
print(debug: "called")
switch result {
case .success(let errorCode):
print(debug: "success: \(errorCode)")
case .failure(let errorCode):
print(debug: "failure: \(errorCode)")
break
}
}
}
...@@ -211,32 +211,29 @@ class ServerSession{ ...@@ -211,32 +211,29 @@ class ServerSession{
func httpBody(boundary: String, _ uploadImage : ReqUploadImage) -> Data! { func httpBody(boundary: String, _ uploadImage : ReqUploadImage) -> Data! {
var httpBody1 = "--\(boundary)\r\n" var httpBody1 = "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"shipId\"\r\n" httpBody1 += "Content-Disposition: form-data; name=\"ShipId\"\r\n"
httpBody1 += "\r\n" httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.shipId)\r\n" httpBody1 += "\(uploadImage.shipId)\r\n"
httpBody1 += "--\(boundary)\r\n" httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"messageId\"\r\n" httpBody1 += "Content-Disposition: form-data; name=\"MessageId\"\r\n"
httpBody1 += "\r\n" httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.messageId)\r\n" httpBody1 += "\(uploadImage.messageId)\r\n"
httpBody1 += "--\(boundary)\r\n" httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"location\"\r\n" httpBody1 += "Content-Disposition: form-data; name=\"Location\"\r\n"
httpBody1 += "\r\n" httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.location)\r\n" httpBody1 += "\(uploadImage.location)\r\n"
httpBody1 += "--\(boundary)\r\n" httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"from\"\r\n" httpBody1 += "Content-Disposition: form-data; name=\"From\"\r\n"
httpBody1 += "\r\n" httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.from)\r\n" httpBody1 += "\(uploadImage.from)\r\n"
httpBody1 += "--\(boundary)\r\n" httpBody1 += "--\(boundary)\r\n"
httpBody1 += "Content-Disposition: form-data; name=\"fromId\"\r\n" httpBody1 += "Content-Disposition: form-data; name=\"FromId\"\r\n"
httpBody1 += "\r\n" httpBody1 += "\r\n"
httpBody1 += "\(uploadImage.fromId)\r\n" httpBody1 += "\(uploadImage.fromId)\r\n"
httpBody1 += "--\(boundary)\r\n" httpBody1 += "--\(boundary)\r\n"
// httpBody1 += "Content-Disposition: form-data; name=\"files\"; filename=\"\(uploadImage.files)\"\r\n"
httpBody1 += "Content-Type: image/jpeg\r\n" httpBody1 += "Content-Type: image/jpeg\r\n"
httpBody1 += "\r\n" httpBody1 += "\r\n"
// var tmp = httpBody1.data(using: .utf8)!
var httpBody = Data() var httpBody = Data()
httpBody.append(httpBody1.data(using: .utf8)!) httpBody.append(httpBody1.data(using: .utf8)!)
httpBody.append(uploadImage.files) httpBody.append(uploadImage.files)
......
//
// SessionNgaList.swift
// Sailassist
//
// Created by 三浦薫巳 on 2024/06/14.
//
import Foundation
import SwiftUI
class SessionNgaList : ObservableObject {
@Published var status = false
// シングルトン宣言
static let OnlyOne = SessionNgaList()
private var serverSession = ServerSession()
private var Calling : Bool = false // 通信中
/**
* タスクリスト取得
*/
func RequestGetNgaList(_ completion: @escaping ((Result<Data, APIError>)) -> Void) {
print(debug: "calld")
if Calling {
return
}
Calling = true
// リクエストURLの組み立て
let id = Preferences.shipId
if id != 0 {
var url_string : String = HttpRequestType.NgaList.rawValue
url_string = url_string.replacingOccurrences(of: "XXXXX", with: String(id))
guard let req_url = URL(string : url_string) else {
Calling = false
return
}
serverSession.getJson(req_url, completion: completion)
}
}
/**
* タスク保存
*/
func RequestPostNgaList(_ nga : ReqNgaList, completion: @escaping ((Result<Data, APIError>)) -> Void) {
print(debug: "calld")
if Calling {
return
}
Calling = true
// リクエストURLの組み立て
let id = Preferences.shipId
if id != 0 {
var url_string : String = HttpRequestType.NgaList.rawValue
url_string = url_string.replacingOccurrences(of: "XXXXX", with: String(id))
guard let req_url = URL(string : url_string) else {
Calling = false
return
}
if let postdata = serverSession.toJSON(nga) {
serverSession.postJson(req_url, postdata, completion: completion)
}
else {
Calling = false
return
}
}
}
/**
* NGAタスク削除
*/
func RequestDeleteNgaList(_ ngaId : String, completion: @escaping ((Result<Data, APIError>)) -> Void) {
print(debug: "calld")
if Calling {
return
}
Calling = true
// リクエストURLの組み立て
let id = Preferences.shipId
if id != 0 {
let strId = String(id) + "/" + ngaId
var url_string : String = HttpRequestType.NgaList.rawValue
url_string = url_string.replacingOccurrences(of: "XXXXX", with: strId)
guard let req_url = URL(string : url_string) else {
Calling = false
return
}
serverSession.deleteJson(req_url, completion: completion)
}
}
}
...@@ -33,8 +33,7 @@ class SessionUploadImage : ObservableObject { ...@@ -33,8 +33,7 @@ class SessionUploadImage : ObservableObject {
return return
} }
// let boundary = "----------" + UUID().uuidString let boundary = "----------" + uploadImage.messageId
let boundary = "----WebKitFormBoundaryZLdHZy8HNaBmUX0d"
if let postdata = serverSession.httpBody(boundary: boundary, uploadImage) { if let postdata = serverSession.httpBody(boundary: boundary, uploadImage) {
serverSession.postForm(boundary: boundary, req_url, postdata, completion: completion) serverSession.postForm(boundary: boundary, req_url, postdata, completion: completion)
} }
......
...@@ -112,23 +112,7 @@ class SharingData{ ...@@ -112,23 +112,7 @@ class SharingData{
@Published var legLine: [CLLocationCoordinate2D] = [] @Published var legLine: [CLLocationCoordinate2D] = []
@Published var portLine: [CLLocationCoordinate2D] = [] @Published var portLine: [CLLocationCoordinate2D] = []
@Published var starboardLine: [CLLocationCoordinate2D] = [] @Published var starboardLine: [CLLocationCoordinate2D] = []
} @Published var isMapFree: Bool = false
static var message = Message()
class Message: ObservableObject {
@Published var mode: Bool = false // false:通常 , true:Warning中
@Published var messages: [ChatMessage] = []
@Published var users: [ChatUser] = []
@Published var viewCnt: Int = 0 //未読数
func changeMode(){
self.mode.toggle()
}
}
static var information = Information()
class Information: ObservableObject {
@Published var content: [ResInformation] = []
} }
/** /**
...@@ -267,6 +251,91 @@ class SharingData{ ...@@ -267,6 +251,91 @@ class SharingData{
} }
} }
/**
* Nga Area
*/
static var nga = Nga()
class Nga: ObservableObject {
@Published var ngaArea: Dictionary<UUID, RegisteredNga> = [:]
@Published var editType = EditNgaType.nonEdit
@Published var editNga: RegisteredNga? = nil
@Published var moveNga: RegisteredNga? = nil
@Published var focusNga: String? = nil
@Published var targetLocation: CLLocationCoordinate2D? = nil //UserMark.movePointLocation
@Published var selectPoint: Int?
func setNgaArea(key: UUID, value: RegisteredNga) {
ngaArea.updateValue(value, forKey: key)
}
func editNgaArea(value: RegisteredNga, type: NgaOperation) {
let setNgaArea = SetNgaArea()
var task = ReqNgaList(Id: value.areaId.uuidString)
switch type {
case NgaOperation.Change:
task.id = value.areaId.uuidString
task.enabled = value.isRunning
task.lock = value.isLock
for point in value.points {
let position = points(lat: point.latitude, lon: point.longitude)
task.geometry.append(position)
}
setNgaArea.start(nga: task)
ngaArea.updateValue(value, forKey: value.areaId)
break
case NgaOperation.Delete:
let deleteNgaArea = DeleteNgaArea()
deleteNgaArea.start(areaId: value.areaId.uuidString)
ngaArea.removeValue(forKey: value.areaId)
break
case NgaOperation.Running:
task.id = value.areaId.uuidString
task.enabled = value.isRunning
task.lock = value.isLock
for point in value.points {
let position = points(lat: point.latitude, lon: point.longitude)
task.geometry.append(position)
}
setNgaArea.start(nga: task)
ngaArea.updateValue(value, forKey: value.areaId)
break
case NgaOperation.Passing:
ngaArea.updateValue(value, forKey: value.areaId)
break
case NgaOperation.Cancel:
task.id = value.areaId.uuidString
task.enabled = value.isRunning
task.lock = value.isLock
for point in value.points {
let position = points(lat: point.latitude, lon: point.longitude)
task.geometry.append(position)
}
setNgaArea.start(nga: task)
ngaArea.updateValue(value, forKey: value.areaId)
break
}
}
}
static var message = Message()
class Message: ObservableObject {
@Published var mode: Bool = false // false:通常 , true:Warning中
@Published var messages: [ChatMessage] = []
@Published var users: [ChatUser] = []
@Published var viewCnt: Int = 0 //未読数
func changeMode(){
self.mode.toggle()
}
}
static var information = Information()
class Information: ObservableObject {
@Published var content: [ResInformation] = []
}
static var pushHistory = PushHistory() static var pushHistory = PushHistory()
class PushHistory: ObservableObject{ class PushHistory: ObservableObject{
@Published var pushHistoryData: Dictionary<Int, ResPushHistory> = [:] @Published var pushHistoryData: Dictionary<Int, ResPushHistory> = [:]
......
...@@ -20,6 +20,14 @@ enum EcaOperation { ...@@ -20,6 +20,14 @@ enum EcaOperation {
case Cancel case Cancel
} }
enum NgaOperation {
case Change
case Delete
case Running
case Cancel
case Passing
}
enum ShipAlert { enum ShipAlert {
case Offline case Offline
case Unknown case Unknown
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
import SwiftUI import SwiftUI
enum Tab: String, CaseIterable{ enum Tab: String, CaseIterable{
case chat = "tab_chat"
case task = "tab_task" case task = "tab_task"
case chat = "tab_chat"
case alert = "tab_notification" case alert = "tab_notification"
case menu = "tab_menu" case menu = "tab_menu"
...@@ -41,7 +41,10 @@ struct MainTabView: View { ...@@ -41,7 +41,10 @@ struct MainTabView: View {
ChatView() ChatView()
.tag(Tab.chat) .tag(Tab.chat)
ZStack {
MapRepresentable() MapRepresentable()
MapInformation()
}
.ignoresSafeArea() .ignoresSafeArea()
.tag(Tab.task) .tag(Tab.task)
...@@ -53,7 +56,7 @@ struct MainTabView: View { ...@@ -53,7 +56,7 @@ struct MainTabView: View {
} }
.hideNativeTabBar() .hideNativeTabBar()
.sheet(isPresented: .constant(isTaskSel && isTabShow && SharingData.my.isFuelSwitchTask), content: { .sheet(isPresented: .constant(isTaskSel && isTabShow && SharingData.my.isFuelSwitchTask), content: {
MapTaskView() MenuTaskView()
.zIndex(0) .zIndex(0)
.presentationDragIndicator(.hidden) .presentationDragIndicator(.hidden)
.presentationDetents([.height(150), .medium, .fraction(0.99)]) .presentationDetents([.height(150), .medium, .fraction(0.99)])
...@@ -81,7 +84,7 @@ struct MainTabView: View { ...@@ -81,7 +84,7 @@ struct MainTabView: View {
} }
.hideNativeTabBar() .hideNativeTabBar()
.popover(isPresented: .constant(isPopover && SharingData.my.isFuelSwitchTask), attachmentAnchor: .point(.bottom)) { .popover(isPresented: .constant(isPopover && SharingData.my.isFuelSwitchTask), attachmentAnchor: .point(.bottom)) {
MapTaskView() MenuTaskView()
.presentationCompactAdaptation(.none) .presentationCompactAdaptation(.none)
.zIndex(0) .zIndex(0)
.frame(minWidth: 300, maxHeight: 500) .frame(minWidth: 300, maxHeight: 500)
......
...@@ -19,10 +19,6 @@ class AlertManager { ...@@ -19,10 +19,6 @@ class AlertManager {
var lastSpeech: String = "" var lastSpeech: String = ""
// 警報を鳴らす。引数の型定義はAlertDB.swift // 警報を鳴らす。引数の型定義はAlertDB.swift
func VocalizeAlert( alertrec : WarnRecord ) {
VocalizeAlert( alertrec: alertrec, identifier: .EcaSwitching)
}
func VocalizeAlert( alertrec : WarnRecord, identifier : PushNotificationTypes.LocalPushIdentifier ) { func VocalizeAlert( alertrec : WarnRecord, identifier : PushNotificationTypes.LocalPushIdentifier ) {
print(debug: "alertrec = \(alertrec)") print(debug: "alertrec = \(alertrec)")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment