Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
Sailassist
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
CpjJwWHV
Sailassist
Commits
95aff94d
Commit
95aff94d
authored
Jun 20, 2024
by
shigemi miura
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
NGA対応
parent
7f096f00
Hide whitespace changes
Inline
Side-by-side
Showing
44 changed files
with
3397 additions
and
661 deletions
+3397
-661
project.pbxproj
Seilassist/Sailassist.xcodeproj/project.pbxproj
+63
-22
Contents.json
...sist/Assets.xcassets/Map/addSymbol.imageset/Contents.json
+21
-0
plus.png
...ailassist/Assets.xcassets/Map/addSymbol.imageset/plus.png
+0
-0
Contents.json
...sist/Assets.xcassets/Map/areaPoint.imageset/Contents.json
+21
-0
areaPoint.png
...sist/Assets.xcassets/Map/areaPoint.imageset/areaPoint.png
+0
-0
Contents.json
...lassist/Assets.xcassets/Map/target.imageset/Contents.json
+21
-0
target.png
...Sailassist/Assets.xcassets/Map/target.imageset/target.png
+0
-0
AlertDB.swift
Seilassist/Sailassist/DataSource/AlertDB.swift
+15
-6
PushNotificationTypes.swift
Seilassist/Sailassist/DataSource/PushNotificationTypes.swift
+2
-0
EcaArea.swift
Seilassist/Sailassist/ECA/EcaArea.swift
+1
-1
EcaTask.swift
Seilassist/Sailassist/ECA/EcaTask.swift
+4
-4
RegisteredEca.swift
Seilassist/Sailassist/ECA/RegisteredEca.swift
+2
-2
HttpRequestType.swift
Seilassist/Sailassist/Http/HttpRequestType.swift
+3
-0
ReqNgaList.swift
Seilassist/Sailassist/Json/ReqNgaList.swift
+19
-0
ReqTaskList.swift
Seilassist/Sailassist/Json/ReqTaskList.swift
+2
-0
LocationCalculation.swift
Seilassist/Sailassist/Location/LocationCalculation.swift
+834
-73
LocationViewModel.swift
Seilassist/Sailassist/LocationViewModel.swift
+4
-1
LoginView.swift
Seilassist/Sailassist/Login/LoginView.swift
+3
-0
InputUserNameView.swift
Seilassist/Sailassist/Login/View/InputUserNameView.swift
+3
-0
LayerEnum.swift
Seilassist/Sailassist/Map/LayerEnum.swift
+0
-18
MapInformation.swift
Seilassist/Sailassist/Map/MapInformation.swift
+52
-0
MapRepresentable.swift
Seilassist/Sailassist/Map/MapRepresentable.swift
+986
-333
MapSource.swift
Seilassist/Sailassist/Map/MapSource.swift
+1
-1
EcaListView.swift
Seilassist/Sailassist/Map/Task/View/EcaListView.swift
+2
-2
EcaSettingView.swift
Seilassist/Sailassist/Map/Task/View/EcaSettingView.swift
+4
-6
FuelSwitchingView.swift
Seilassist/Sailassist/Map/Task/View/FuelSwitchingView.swift
+4
-14
MapTaskView.swift
Seilassist/Sailassist/Map/Task/View/MapTaskView.swift
+0
-135
MenuTaskView.swift
Seilassist/Sailassist/Map/Task/View/MenuTaskView.swift
+450
-0
NgaNotificationView.swift
...assist/Sailassist/Map/Task/View/NgaNotificationView.swift
+135
-0
NgaSettingView.swift
Seilassist/Sailassist/Map/Task/View/NgaSettingView.swift
+306
-0
TaskViewModel.swift
Seilassist/Sailassist/Map/Task/ViewModel/TaskViewModel.swift
+2
-2
MenuTitleView.swift
Seilassist/Sailassist/Menu/View/MenuTitleView.swift
+1
-1
DeleteNgaArea.swift
Seilassist/Sailassist/NGA/DeleteNgaArea.swift
+28
-0
GetNgaList.swift
Seilassist/Sailassist/NGA/GetNgaList.swift
+70
-0
NgaTask.swift
Seilassist/Sailassist/NGA/NgaTask.swift
+62
-0
RegistereNga.swift
Seilassist/Sailassist/NGA/RegistereNga.swift
+37
-0
SetNgaArea.swift
Seilassist/Sailassist/NGA/SetNgaArea.swift
+30
-0
ServerSession.swift
Seilassist/Sailassist/ServerSession/ServerSession.swift
+5
-8
SessionNgaList.swift
Seilassist/Sailassist/ServerSession/SessionNgaList.swift
+97
-0
SessionUploadImage.swift
Seilassist/Sailassist/ServerSession/SessionUploadImage.swift
+1
-2
SharingData.swift
Seilassist/Sailassist/SharingData/SharingData.swift
+89
-20
StatusEnum.swift
Seilassist/Sailassist/SharingData/StatusEnum.swift
+8
-0
MainTabView.swift
Seilassist/Sailassist/Tab/MainTabView.swift
+9
-6
AlertManager.swift
Seilassist/Sailassist/VoiceManager/AlertManager.swift
+0
-4
No files found.
Seilassist/Sailassist.xcodeproj/project.pbxproj
View file @
95aff94d
...
...
@@ -62,12 +62,9 @@
02C3E5D12AFCC16800AF7837
/* ChatTitleView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
02C3E5D02AFCC16800AF7837
/* ChatTitleView.swift */
;
};
02C3E6092AFDF30000AF7837
/* ChatMemberView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
02C3E6082AFDF30000AF7837
/* ChatMemberView.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 */
;
};
02CD06952AE895F5005F8D8F
/* APIError.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
02CD06942AE895F5005F8D8F
/* APIError.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 */
;
};
02CE4D892ADF62E1002E79BC
/* EcaSettingView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
02CE4D882ADF62E1002E79BC
/* EcaSettingView.swift */
;
};
02CE4DC82ADF97E8002E79BC
/* View+Extensions.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
02CE4DC72ADF97E8002E79BC
/* View+Extensions.swift */
;
};
...
...
@@ -92,17 +89,21 @@
D52D213F2AEBB7D700324D58
/* RegisteredEca.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D52D213E2AEBB7D700324D58
/* RegisteredEca.swift */
;
};
D52D21412AEDE18F00324D58
/* EcaCoordinatesTable.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D52D21402AEDE18F00324D58
/* EcaCoordinatesTable.swift */
;
};
D536F6712B678D8900A5BCF9
/* ReqUploadImage.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D536F6702B678D8900A5BCF9
/* ReqUploadImage.swift */
;
};
D5384AFC2B306CEF006228C6
/* TermsView.html in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D5384AFB2B306CEF006228C6
/* TermsView.html */
;
};
D5384AFE2B3121F2006228C6
/* PrivacyView.html in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D5384AFD2B3121F2006228C6
/* PrivacyView.html */
;
};
D539F3302C1809790088E609
/* NgaTask.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D539F32F2C1809790088E609
/* NgaTask.swift */
;
};
D53B97262B341867000B3D29
/* AboutAppView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D53B97252B341867000B3D29
/* AboutAppView.swift */
;
};
D545FC742B09C74300F206D0
/* AlertManager.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D545FC732B09C74300F206D0
/* AlertManager.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 */
;
};
D54D174B2B35137A00A0EAA5
/* LocalWebView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D54D174A2B35137A00A0EAA5
/* LocalWebView.swift */
;
};
D54D17512B35923400A0EAA5
/* GetManualUrl.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D54D17502B35923400A0EAA5
/* GetManualUrl.swift */
;
};
D55135202B15B030007B66B1
/* SetEcaArea.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D551351F2B15B030007B66B1
/* SetEcaArea.swift */
;
};
D55135222B15C062007B66B1
/* GetEcaList.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D55135212B15C062007B66B1
/* GetEcaList.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 */
;
};
D58E1F522B142A3F0092D8FE
/* ResEcaArea.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D58E1F512B142A3F0092D8FE
/* ResEcaArea.swift */
;
};
D58E1F542B142A510092D8FE
/* SessionEcaArea.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D58E1F532B142A510092D8FE
/* SessionEcaArea.swift */
;
};
...
...
@@ -124,6 +125,12 @@
D5B493A12B48E930008B3620
/* privacy.html in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D5B4939F2B48E930008B3620
/* privacy.html */
;
};
D5B493A42B48EE50008B3620
/* Manual in Resources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D5B493A32B48EE50008B3620
/* Manual */
;
};
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 */
;
};
D5CB6F9B2B021C4F00EC2010
/* LocationViewModel.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D5CB6F9A2B021C4F00EC2010
/* LocationViewModel.swift */
;
};
D5CB6F9F2B0220A700EC2010
/* ErrorView.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
D5CB6F9E2B0220A700EC2010
/* ErrorView.swift */
;
};
...
...
@@ -227,12 +234,9 @@
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
;
};
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>"
;
};
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>"
;
};
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>"
;
};
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>"
;
};
...
...
@@ -265,18 +269,22 @@
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
;
};
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
;
};
D5384AFD2B3121F2006228C6
/* PrivacyView.html */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
text.html
;
name
=
PrivacyView.html
;
path
=
SailAssist/html/PrivacyView.html
;
sourceTree
=
SOURCE_ROOT
;
};
D539F32F2C1809790088E609
/* NgaTask.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
NgaTask.swift
;
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
;
};
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
;
};
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
;
};
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
;
};
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
;
};
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
;
};
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
;
};
...
...
@@ -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
;
};
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
;
};
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
;
};
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
;
};
...
...
@@ -371,6 +385,7 @@
020B98122AD8C3140029DE4C
/* SailAssist */
=
{
isa
=
PBXGroup
;
children
=
(
D5C782452BFB55F0001EBB3A
/* NGA */
,
D5384AFF2B3121FA006228C6
/* html */
,
D545FC722B09C6DA00F206D0
/* VoiceManager */
,
D51AA4052B099F6D00EBBDD4
/* DataSource */
,
...
...
@@ -457,8 +472,8 @@
0227890F2AE6028000A87787
/* Task */
,
02CE4DD92ADFBA72002E79BC
/* MapRepresentable.swift */
,
02CD068E2AE6535F005F8D8F
/* MapSource.swift */
,
02CD06902AE6536B005F8D8F
/* LayerEnum.swift */
,
D5258C9A2B03401E00365276
/* MonitoringRoute.swift */
,
D546B0122C197BB50058CD98
/* MapInformation.swift */
,
);
path
=
Map
;
sourceTree
=
"<group>"
;
...
...
@@ -563,10 +578,12 @@
022789102AE6028400A87787
/* View */
=
{
isa
=
PBXGroup
;
children
=
(
02CE4D822ADE672B002E79BC
/* MapTaskView.swift */
,
02CE4D842ADF6295002E79BC
/* TaskSwitchingMenuView.swift */
,
D5C7823B2BFB4CEF001EBB3A
/* FuelSwitchingView.swift */
,
D5C782392BFB4C2A001EBB3A
/* NgaNotificationView.swift */
,
D5C7822E2BF88755001EBB3A
/* MenuTaskView.swift */
,
02CE4D862ADF62A7002E79BC
/* EcaListView.swift */
,
02CE4D882ADF62E1002E79BC
/* EcaSettingView.swift */
,
D5C782482BFC2DA2001EBB3A
/* NgaSettingView.swift */
,
);
path
=
View
;
sourceTree
=
"<group>"
;
...
...
@@ -596,6 +613,7 @@
02F4DB662B2C173F00E86C41
/* SessionGetManualUrl.swift */
,
D58EF2442B901D3900FB784C
/* SessionInformation.swift */
,
D58EF2482B90562B00FB784C
/* GetInformation.swift */
,
D57905FF2C1C06F600AF797C
/* SessionNgaList.swift */
,
);
path
=
ServerSession
;
sourceTree
=
"<group>"
;
...
...
@@ -774,10 +792,24 @@
D5FCEF562B4789A8009A81D0
/* ResAckMessage.swift */
,
D5FCEF582B4789D2009A81D0
/* ResChatMode.swift */
,
D536F6702B678D8900A5BCF9
/* ReqUploadImage.swift */
,
D57906012C1C0CFB00AF797C
/* ReqNgaList.swift */
,
);
path
=
Json
;
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 */
=
{
isa
=
PBXGroup
;
children
=
(
...
...
@@ -992,7 +1024,7 @@
D55135222B15C062007B66B1
/* GetEcaList.swift in Sources */
,
D52D21412AEDE18F00324D58
/* EcaCoordinatesTable.swift in Sources */
,
02A1DE2F2AFB4AA0005BCF55
/* ChatInputView.swift in Sources */
,
02CD06912AE6536B005F8D8F
/* LayerEnum
.swift in Sources */
,
D57905FE2C1C069000AF797C
/* SetNgaArea
.swift in Sources */
,
020B98532AD919180029DE4C
/* LoginTypeSelectView.swift in Sources */
,
D52D213F2AEBB7D700324D58
/* RegisteredEca.swift in Sources */
,
02CD06952AE895F5005F8D8F
/* APIError.swift in Sources */
,
...
...
@@ -1002,9 +1034,12 @@
022A98202AF8B8960079C55A
/* LocationCalculation.swift in Sources */
,
D5258CA72B03988600365276
/* ReqTaskList.swift in Sources */
,
D5CB6F9B2B021C4F00EC2010
/* LocationViewModel.swift in Sources */
,
D5C7823C2BFB4CEF001EBB3A
/* FuelSwitchingView.swift in Sources */
,
D58E06D02C1D1AF20039F22C
/* GetNgaList.swift in Sources */
,
02CE4DC82ADF97E8002E79BC
/* View+Extensions.swift in Sources */
,
025F99742B2C125900C9A18A
/* ResGetManualUrl.swift in Sources */
,
D58E1F542B142A510092D8FE
/* SessionEcaArea.swift in Sources */
,
D5C7823A2BFB4C2A001EBB3A
/* NgaNotificationView.swift in Sources */
,
025C28002B034A1900BADC49
/* PDFViewer.swift in Sources */
,
02C3E6092AFDF30000AF7837
/* ChatMemberView.swift in Sources */
,
020B98412AD8C3810029DE4C
/* LoginView.swift in Sources */
,
...
...
@@ -1020,20 +1055,23 @@
02F4DB672B2C173F00E86C41
/* SessionGetManualUrl.swift in Sources */
,
D5AE351B2AEBA66A00059889
/* ResLogin.swift in Sources */
,
D592D5252B0F16CA00B91A1C
/* ReqMessage.swift in Sources */
,
02CE4D832ADE672B002E79BC
/* MapTaskView
.swift in Sources */
,
D5C782472BFB55F0001EBB3A
/* RegistereNga
.swift in Sources */
,
02CE4DCC2ADFA03F002E79BC
/* SelectedTabModel.swift in Sources */
,
D5258C9B2B03401E00365276
/* MonitoringRoute.swift in Sources */
,
D57906022C1C0CFB00AF797C
/* ReqNgaList.swift in Sources */
,
020B98162AD8C3150029DE4C
/* ContentView.swift in Sources */
,
020B98632ADD14E50029DE4C
/* ChatView.swift in Sources */
,
02CE4DDA2ADFBA72002E79BC
/* MapRepresentable.swift in Sources */
,
020B985E2ADCFF130029DE4C
/* PreferencesKey.swift in Sources */
,
0227890C2AE22E0B00A87787
/* SharingData.swift in Sources */
,
D57906002C1C06F600AF797C
/* SessionNgaList.swift in Sources */
,
020B984D2AD9178F0029DE4C
/* ScannerViewModel.swift in Sources */
,
020B98142AD8C3140029DE4C
/* SailassistApp.swift in Sources */
,
02CE4D852ADF6295002E79BC
/* TaskSwitchingMenuView
.swift in Sources */
,
D546B0132C197BB50058CD98
/* MapInformation
.swift in Sources */
,
D5CB6F9F2B0220A700EC2010
/* ErrorView.swift in Sources */
,
D5CB6F992B02088C00EC2010
/* ResShipStatus.swift in Sources */
,
023DB8282B1429E400B351CF
/* NotificationContentView.swift in Sources */
,
D5C7822F2BF88755001EBB3A
/* MenuTaskView.swift in Sources */
,
027EF9F22B0D804C0079B825
/* WebView.swift in Sources */
,
020B984B2AD915810029DE4C
/* QRReadView.swift in Sources */
,
02A1DE332AFB654A005BCF55
/* CustomCornerRadius.swift in Sources */
,
...
...
@@ -1050,6 +1088,7 @@
025C27FE2B0206D700BADC49
/* PDFDownloadManager.swift in Sources */
,
D59908CA2B1AC381000E13DD
/* GetPushHistory.swift in Sources */
,
D54D174B2B35137A00A0EAA5
/* LocalWebView.swift in Sources */
,
D539F3302C1809790088E609
/* NgaTask.swift in Sources */
,
D5FCEF572B4789A8009A81D0
/* ResAckMessage.swift in Sources */
,
025C27FC2AFE191A00BADC49
/* MenuManualView.swift in Sources */
,
D58E1F502B142A260092D8FE
/* EcaArea.swift in Sources */
,
...
...
@@ -1064,6 +1103,8 @@
D5E03A672B04484D00D65FCE
/* SessionTaskList.swift in Sources */
,
020B986E2ADD3E8D0029DE4C
/* DateTextLib.swift in Sources */
,
D5258C9D2B03507A00365276
/* ResMonitoringRoute.swift in Sources */
,
D5C782462BFB55F0001EBB3A
/* DeleteNgaArea.swift in Sources */
,
D5C782492BFC2DA2001EBB3A
/* NgaSettingView.swift in Sources */
,
020B98672ADD15050029DE4C
/* MenuView.swift in Sources */
,
020B98572AD924F50029DE4C
/* CameraPreview.swift in Sources */
,
D5CB6FA12B023F7F00EC2010
/* EcaTask.swift in Sources */
,
...
...
@@ -1258,7 +1299,7 @@
CODE_SIGN_ENTITLEMENTS
=
Sailassist/Sailassist.entitlements
;
CODE_SIGN_IDENTITY
=
"Apple Development"
;
CODE_SIGN_STYLE
=
Automatic
;
CURRENT_PROJECT_VERSION
=
2
2
;
CURRENT_PROJECT_VERSION
=
2
5
;
DEVELOPMENT_ASSET_PATHS
=
"\"Sailassist/Preview Content\""
;
DEVELOPMENT_TEAM
=
D2DC7QNNJ8
;
ENABLE_PREVIEWS
=
YES
;
...
...
@@ -1282,7 +1323,7 @@
"$(inherited)"
,
"@executable_path/Frameworks"
,
);
MARKETING_VERSION
=
1.0.
2
;
MARKETING_VERSION
=
1.0.
3
;
OTHER_SWIFT_FLAGS
=
"-D CANARY -D COCOAPODS"
;
PRODUCT_BUNDLE_IDENTIFIER
=
com.jrc.sailassist.canary
;
PRODUCT_NAME
=
"Sail Assist"
;
...
...
@@ -1304,7 +1345,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME
=
AccentColor
;
CODE_SIGN_ENTITLEMENTS
=
Sailassist/Sailassist.entitlements
;
CODE_SIGN_STYLE
=
Automatic
;
CURRENT_PROJECT_VERSION
=
2
2
;
CURRENT_PROJECT_VERSION
=
2
5
;
DEVELOPMENT_ASSET_PATHS
=
"\"Sailassist/Preview Content\""
;
DEVELOPMENT_TEAM
=
D2DC7QNNJ8
;
ENABLE_PREVIEWS
=
YES
;
...
...
@@ -1325,7 +1366,7 @@
"$(inherited)"
,
"@executable_path/Frameworks"
,
);
MARKETING_VERSION
=
1.0.
2
;
MARKETING_VERSION
=
1.0.
3
;
OTHER_SWIFT_FLAGS
=
"-D COCOAPODS"
;
PRODUCT_BUNDLE_IDENTIFIER
=
com.jrc.sailassist
;
PRODUCT_NAME
=
"Sail Assist"
;
...
...
@@ -1488,7 +1529,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME
=
AccentColor
;
CODE_SIGN_ENTITLEMENTS
=
Sailassist/Sailassist.entitlements
;
CODE_SIGN_STYLE
=
Automatic
;
CURRENT_PROJECT_VERSION
=
2
2
;
CURRENT_PROJECT_VERSION
=
2
5
;
DEVELOPMENT_ASSET_PATHS
=
"\"Sailassist/Preview Content\""
;
DEVELOPMENT_TEAM
=
D2DC7QNNJ8
;
ENABLE_PREVIEWS
=
YES
;
...
...
@@ -1512,7 +1553,7 @@
"$(inherited)"
,
"@executable_path/Frameworks"
,
);
MARKETING_VERSION
=
1.0.
2
;
MARKETING_VERSION
=
1.0.
3
;
OTHER_SWIFT_FLAGS
=
"-D QC -D COCOAPODS"
;
PRODUCT_BUNDLE_IDENTIFIER
=
com.jrc.sailassist.qc
;
PRODUCT_NAME
=
"Sail Assist"
;
...
...
Seilassist/Sailassist/Assets.xcassets/Map/addSymbol.imageset/Contents.json
0 → 100644
View file @
95aff94d
{
"images"
:
[
{
"filename"
:
"plus.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
Seilassist/Sailassist/Assets.xcassets/Map/addSymbol.imageset/plus.png
0 → 100644
View file @
95aff94d
530 Bytes
Seilassist/Sailassist/Assets.xcassets/Map/areaPoint.imageset/Contents.json
0 → 100644
View file @
95aff94d
{
"images"
:
[
{
"filename"
:
"areaPoint.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
Seilassist/Sailassist/Assets.xcassets/Map/areaPoint.imageset/areaPoint.png
0 → 100644
View file @
95aff94d
680 Bytes
Seilassist/Sailassist/Assets.xcassets/Map/target.imageset/Contents.json
0 → 100644
View file @
95aff94d
{
"images"
:
[
{
"filename"
:
"target.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
Seilassist/Sailassist/Assets.xcassets/Map/target.imageset/target.png
0 → 100644
View file @
95aff94d
257 Bytes
Seilassist/Sailassist/DataSource/AlertDB.swift
View file @
95aff94d
...
...
@@ -12,11 +12,13 @@ struct WarnRecord {
var
body
:
String
}
enum
Switching
Eca
{
enum
Switching
Alert
{
case
Finish
case
Start
case
Notice
case
NgaPassing
init
()
{
self
=
.
Notice
}
...
...
@@ -26,14 +28,21 @@ class AlertDB {
// シングルトン宣言
static
let
OnlyOne
=
AlertDB
()
private
var
alertEca
:
[
SwitchingEca
:
WarnRecord
]
=
[
SwitchingEca
.
Finish
:
WarnRecord
(
title
:
NSLocalizedString
(
"No Fuel Switching Finished"
,
comment
:
""
),
body
:
NSLocalizedString
(
"Arrived at switching finished point."
,
comment
:
""
))
,
SwitchingEca
.
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
:
""
))
private
var
alertEca
:
[
SwitchingAlert
:
WarnRecord
]
=
[
SwitchingAlert
.
Finish
:
WarnRecord
(
title
:
String
(
"No Fuel Switching Finished"
),
body
:
String
(
"Arrived at switching finished point."
)),
SwitchingAlert
.
Start
:
WarnRecord
(
title
:
NSLocalizedString
(
"Eca Start"
,
comment
:
""
),
body
:
NSLocalizedString
(
"Arrived at switching start 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通知
func
GetAlertEcaPoint
(
point
:
SwitchingEca
)
->
WarnRecord
{
func
GetAlertEcaPoint
(
point
:
SwitchingAlert
)
->
WarnRecord
{
return
alertEca
[
point
]
!
}
//Nga通知
func
GetAlertNgaPoint
(
point
:
SwitchingAlert
)
->
WarnRecord
{
return
alertEca
[
point
]
!
}
}
Seilassist/Sailassist/DataSource/PushNotificationTypes.swift
View file @
95aff94d
...
...
@@ -12,6 +12,7 @@ struct PushNotificationTypes {
enum
SendType
:
Int32
{
case
Error
=
-
1
case
Eca
=
0
// Eca
case
Nga
=
1
//Nga
init
(){
self
=
.
Error
...
...
@@ -29,5 +30,6 @@ struct PushNotificationTypes {
enum
LocalPushIdentifier
:
String
{
case
Reserve
=
"Reserve"
// 予約(初期設定)
case
EcaSwitching
=
"Eca"
// Eca
case
NgaAlert
=
"Nga"
// Nga
}
}
Seilassist/Sailassist/ECA/EcaArea.swift
View file @
95aff94d
...
...
@@ -47,7 +47,7 @@ class EcaArea {
private
func
tableInit
()
{
for
data
in
ecaDataTable
{
if
!
ecaData
.
ecaArea
.
keys
.
contains
(
data
.
areaId
)
{
var
reg
=
RegisteredEca
(
id
:
data
.
areaId
,
ec
aName
:
data
.
name
)
!
var
reg
=
RegisteredEca
(
id
:
data
.
areaId
,
are
aName
:
data
.
name
)
!
reg
.
color
=
"0xFF0000"
//ライン色(ARGB)
reg
.
centerPosition
=
data
.
centerPosition
reg
.
zoomLevel
=
data
.
zoomLevel
...
...
Seilassist/Sailassist/ECA/EcaTask.swift
View file @
95aff94d
...
...
@@ -20,7 +20,7 @@ class EcaTask {
/**
* Eca通知
*/
private
func
notificationEca
(
point
:
Switching
Eca
)
{
private
func
notificationEca
(
point
:
Switching
Alert
)
{
let
alertDB
=
AlertDB
.
OnlyOne
var
wernrec
=
WarnRecord
(
title
:
"Eca"
,
body
:
""
)
...
...
@@ -75,7 +75,7 @@ class EcaTask {
// }
if
eca
.
swFinish
>=
Float
(
distance
)
&&
0.0
<
Float
(
distance
)
&&
SharingData
.
my
.
ecaStatus
!=
EcaState
.
finishPass
{
// notificationEca(point: Switching
Eca
.Finish)
// notificationEca(point: Switching
Alert
.Finish)
SharingData
.
eca
.
isShowEcaAlert
=
true
SharingData
.
my
.
ecaStatus
=
EcaState
.
finishPass
...
...
@@ -84,7 +84,7 @@ class EcaTask {
}
if
eca
.
swStart
>=
Float
(
distance
)
&&
eca
.
swFinish
<
Float
(
distance
)
&&
SharingData
.
my
.
ecaStatus
!=
EcaState
.
startPass
{
notificationEca
(
point
:
Switching
Eca
.
Start
)
notificationEca
(
point
:
Switching
Alert
.
Start
)
SharingData
.
eca
.
isShowEcaAlert
=
true
SharingData
.
my
.
ecaStatus
=
EcaState
.
startPass
...
...
@@ -93,7 +93,7 @@ class EcaTask {
}
if
eca
.
swNotice
>=
Float
(
distance
)
&&
eca
.
swStart
<
Float
(
distance
)
&&
SharingData
.
my
.
ecaStatus
!=
EcaState
.
noticePass
{
notificationEca
(
point
:
Switching
Eca
.
Notice
)
notificationEca
(
point
:
Switching
Alert
.
Notice
)
SharingData
.
eca
.
isShowEcaAlert
=
true
SharingData
.
my
.
ecaStatus
=
EcaState
.
noticePass
...
...
Seilassist/Sailassist/ECA/RegisteredEca.swift
View file @
95aff94d
...
...
@@ -44,8 +44,8 @@ struct RegisteredEca {
var
zoomLevel
:
CGFloat
=
11.0
var
points
:
[
CLLocationCoordinate2D
]
=
[]
init
?(
id
:
Int
,
ec
aName
:
String
)
{
init
?(
id
:
Int
,
are
aName
:
String
)
{
self
.
areaId
=
id
self
.
name
=
ec
aName
self
.
name
=
are
aName
}
}
Seilassist/Sailassist/Http/HttpRequestType.swift
View file @
95aff94d
...
...
@@ -16,6 +16,7 @@ enum HttpRequestType : String {
// case CookiePolicy = "https://ssv-canary-web.azurewebsites.net/cookiepolicy"
// case PrivacyPolicy = "https://ssv-canary-web.azurewebsites.net/inapp?" //+バージョン番号
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
ShipStatus
=
"https://ssv-canary-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX"
case
ShipMonitoringRoute
=
"https://ssv-canary-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX"
...
...
@@ -42,6 +43,7 @@ enum HttpRequestType : String {
// case CookiePolicy = "https://ssv-qc-web.azurewebsites.net/cookiepolicy"
// case PrivacyPolicy = "https://ssv-qc-web.azurewebsites.net/inapp?" //+バージョン番号
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
ShipStatus
=
"https://ssv-qc-web.azurewebsites.net/api/sailassist/shipstatus/XXXXX"
case
ShipMonitoringRoute
=
"https://ssv-qc-web.azurewebsites.net/api/sailassist/shipmonitoringroute/XXXXX"
...
...
@@ -69,6 +71,7 @@ enum HttpRequestType : String {
// case CookiePolicy = "https://ssv.jmarinecloud.com/cookiepolicy"
// case PrivacyPolicy = "https://ssv.jmarinecloud.com/inapp?" //+バージョン番号
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
ShipStatus
=
"https://ssv.jmarinecloud.com/api/sailassist/shipstatus/XXXXX"
case
ShipMonitoringRoute
=
"https://ssv.jmarinecloud.com/api/sailassist/shipmonitoringroute/XXXXX"
...
...
Seilassist/Sailassist/Json/ReqNgaList.swift
0 → 100644
View file @
95aff94d
//
// 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
}
}
Seilassist/Sailassist/Json/ReqTaskList.swift
View file @
95aff94d
...
...
@@ -8,8 +8,10 @@
import
Foundation
struct
ReqTaskList
:
Codable
{
// var id: String = ""
var
areaId
:
Int
=
0
var
taskName
:
String
=
""
// var name: String = ""
var
noticeRange
:
Float
=
0.0
var
startRange
:
Float
=
0.0
var
finishRange
:
Float
=
0.0
...
...
Seilassist/Sailassist/Location/LocationCalculation.swift
View file @
95aff94d
...
...
@@ -10,35 +10,45 @@ import Foundation
import
CoreLocation
// import Mapbox
struct
PointC
{
var
x
:
Int
var
y
:
Int
}
class
LocationCalculation
{
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に変換
*/
static
func
nm2km
(
nm
:
Double
)
->
Double
{
return
nm
*
1.852
}
/**
* kmをNMに変換
*/
static
func
km2nm
(
km
:
Double
)
->
Double
{
return
km
/
1.852
}
static
func
kn2kmh
(
kn
:
Double
)
->
Double
{
return
kn
*
1.852
}
static
func
deg2rad
(
deg
:
Double
)
->
Double
{
return
(
deg
/
180.0
)
*
Double
.
pi
}
static
func
rad2deg
(
rad
:
Double
)
->
Double
{
return
(
rad
/
Double
.
pi
)
*
180.0
}
/**
* 地理座標の確認
*/
...
...
@@ -65,7 +75,7 @@ class LocationCalculation{
return
rangeDegree
}
/// 2点間距離の算出
/// - Parameters:
/// - posAlat: 地点A緯度
...
...
@@ -83,12 +93,12 @@ class LocationCalculation{
let
lonDifference
=
deg2rad
(
deg
:
posAlon
-
posBlon
)
let
curRadiusTemp
=
1
-
0.00669438
*
pow
(
sin
(
latAvg
),
2.0
)
//子午線曲率半径
let
meridianCurvatureRadius
=
6335439.327
/
sqrt
(
pow
(
curRadiusTemp
,
3.0
))
//卯酉線曲率半径
let
primeVerticalCircleCurvatureRadius
=
6378137
/
sqrt
(
curRadiusTemp
)
//2点間距離
let
distanceTemp
=
pow
(
meridianCurvatureRadius
*
latDifference
,
2.0
)
+
pow
(
primeVerticalCircleCurvatureRadius
*
cos
(
latAvg
)
*
lonDifference
,
2.0
)
return
sqrt
(
distanceTemp
)
//メートル単位
...
...
@@ -102,7 +112,7 @@ class LocationCalculation{
static
func
distance
(
posA
:
CLLocationCoordinate2D
,
posB
:
CLLocationCoordinate2D
)
->
Double
{
return
distance
(
posAlat
:
posA
.
latitude
,
posAlon
:
posA
.
longitude
,
posBlat
:
posB
.
latitude
,
posBlon
:
posB
.
longitude
)
}
/// 地点Bから地点Aをみたときの方位角
/// - Parameters:
/// - posAlat: 地点A緯度
...
...
@@ -116,7 +126,7 @@ class LocationCalculation{
let
posA_lon
=
deg2rad
(
deg
:
posAlon
)
let
posB_lat
=
deg2rad
(
deg
:
posBlat
)
let
posB_lon
=
deg2rad
(
deg
:
posBlon
)
//経度の中心地
let
posC_lat
=
(
posA_lat
+
posB_lat
)
/
2.0
let
dx
=
6378137
*
(
posB_lon
-
posA_lon
)
*
cos
(
posC_lat
)
...
...
@@ -125,14 +135,14 @@ class LocationCalculation{
if
(
dx
==
dy
){
return
0.0
}
//なぜか左向きが0度、反時計回りに増える
let
deg
=
rad2deg
(
rad
:
atan2
(
dy
,
dx
))
//それを修正
let
deg_o
=
deg
+
90
let
deg_p
=
360
-
deg_o
if
(
deg_p
>=
360
)
{
return
deg_p
-
360
}
else
{
...
...
@@ -140,7 +150,6 @@ class LocationCalculation{
}
}
/// 起点から指定の距離方位分移動した地点の緯度経度
/// - Parameters:
/// - startPointLat: 起点緯度
...
...
@@ -154,26 +163,26 @@ class LocationCalculation{
startPointLon
:
Double
,
initialBearing
:
Double
,
distanceKilometers
:
Double
)
->
CLLocationCoordinate2D
{
let
initialBearingRadians
=
initialBearing
*
2.0
*
Double
.
pi
/
360.0
let
radiusEarthKilometers
=
6371.01
let
distRatio
=
distanceKilometers
/
radiusEarthKilometers
let
distRatioSine
=
sin
(
distRatio
)
let
distRatioCosine
=
cos
(
distRatio
)
let
startLatRad
=
deg2rad
(
deg
:
startPointLat
)
let
startLonRad
=
deg2rad
(
deg
:
startPointLon
)
let
initialBearingRadians
=
initialBearing
*
2.0
*
Double
.
pi
/
360.0
let
radiusEarthKilometers
=
6371.01
let
distRatio
=
distanceKilometers
/
radiusEarthKilometers
let
distRatioSine
=
sin
(
distRatio
)
let
distRatioCosine
=
cos
(
distRatio
)
let
startLatCos
=
cos
(
startLatRad
)
let
startLatSin
=
sin
(
startLatRad
)
let
startLatRad
=
deg2rad
(
deg
:
startPointLat
)
let
startLonRad
=
deg2rad
(
deg
:
startPointLon
)
let
endLatRads
=
asin
((
startLatSin
*
distRatioCosine
)
+
(
startLatCos
*
distRatioSine
*
cos
(
initialBearingRadians
)))
let
startLatCos
=
cos
(
startLatRad
)
let
startLatSin
=
sin
(
startLatRad
)
let
endLonRads
=
startLonRad
+
atan2
(
sin
(
initialBearingRadians
)
*
distRatioSine
*
startLatCos
,
distRatioCosine
-
startLatSin
*
sin
(
endLatRads
))
let
endLatRads
=
asin
((
startLatSin
*
distRatioCosine
)
+
(
startLatCos
*
distRatioSine
*
cos
(
initialBearingRadians
)))
let
endLonRads
=
startLonRad
+
atan2
(
sin
(
initialBearingRadians
)
*
distRatioSine
*
startLatCos
,
distRatioCosine
-
startLatSin
*
sin
(
endLatRads
))
return
CLLocationCoordinate2D
(
latitude
:
rad2deg
(
rad
:
endLatRads
),
longitude
:
rad2deg
(
rad
:
endLonRads
))
}
return
CLLocationCoordinate2D
(
latitude
:
rad2deg
(
rad
:
endLatRads
),
longitude
:
rad2deg
(
rad
:
endLonRads
))
}
/// 地点Aと地点Bをの間の位置
/// - Parameters:
/// - posAlat: 地点A緯度
...
...
@@ -183,20 +192,23 @@ class LocationCalculation{
/// - Returns:
/// 2地点間の中間緯度経度
static
func
halfPoint
(
posAlat
:
Double
,
posAlon
:
Double
,
posBlat
:
Double
,
posBlon
:
Double
)
->
CLLocationCoordinate2D
{
let
lat
=
(
posAlat
+
posBlat
)
/
2
let
lon
=
(
posAlon
+
posBlon
)
/
2
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の中心の位置
/// - Parameters:
/// - positions: 地点配列
/// - Returns:
/// Polygonの中間緯度経度
static
func
CenterPoint
(
positions
:
[
CLLocationCoordinate2D
])
->
CLLocationCoordinate2D
{
var
latMax
:
Double
=
0
var
latMin
:
Double
=
360
var
lonMax
:
Double
=
0
...
...
@@ -220,7 +232,36 @@ class LocationCalculation{
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:
/// - lat: 緯度数値
...
...
@@ -233,20 +274,22 @@ class LocationCalculation{
}
else
{
latNS
=
"S"
}
let
latNum
:
Double
if
(
lat
>=
0
)
{
latNum
=
lat
}
else
{
latNum
=
-
lat
}
let
latDeg
=
Int32
(
latNum
)
let
latMin
=
(
latNum
-
Double
(
latDeg
))
*
60.0
return
"
\(
latDeg
)
°
\(
String
(
format
:
"%06.3f"
,
latMin
)
)
′
\(
latNS
)
"
}
/// 経度を数値から文字列に変換
/// - Parameters:
/// - lon: 経度数値
...
...
@@ -259,20 +302,61 @@ class LocationCalculation{
}
else
{
lonEW
=
"W"
}
let
lonNum
:
Double
if
(
lon
>=
0
){
lonNum
=
lon
}
else
{
lonNum
=
-
lon
}
let
lonDeg
=
Int32
(
lonNum
)
let
lonMin
=
(
lonNum
-
Double
(
lonDeg
))
*
60.0
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
...
...
@@ -306,7 +390,6 @@ class LocationCalculation{
}
else
{
return
nil
}
}
/**
...
...
@@ -343,7 +426,115 @@ class LocationCalculation{
return
nil
}
}
/// 緯度の数値を分解
/// - 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 -> 時計回り
/// -1 -> 反時計回り
...
...
@@ -366,7 +557,7 @@ class LocationCalculation{
}
}
}
/// 地点Bから地点Aをみたときの方位角文字列
/// - Parameters:
/// - posAlat: 地点A緯度
...
...
@@ -380,7 +571,7 @@ class LocationCalculation{
return
String
(
round
(
direction
))
+
"°"
}
///距離(NM)を文字列に変換
static
func
distance2Str
(
nm
:
Double
)
->
String
{
var
rtnStr
=
""
...
...
@@ -393,7 +584,7 @@ class LocationCalculation{
}
return
rtnStr
}
static
let
rad45
=
0.785398163397448
// radで45°
static
let
rDeg
=
57.295779513082323
// radからdegに変換する乗数
static
let
eEccentricity
=
0.08181919
// 離心率
...
...
@@ -403,10 +594,10 @@ class LocationCalculation{
static
let
errorRange
=
0.00001
//誤差範囲
struct
AreaLatLon
{
var
NorthLat
:
Double
=
0.0
var
SouthLat
:
Double
=
0.0
var
EastLon
:
Double
=
0.0
var
WestLon
:
Double
=
0.0
var
NorthLat
:
CLLocationDegrees
=
0.0
var
SouthLat
:
CLLocationDegrees
=
0.0
var
EastLon
:
CLLocationDegrees
=
0.0
var
WestLon
:
CLLocationDegrees
=
0.0
}
/**
...
...
@@ -423,7 +614,7 @@ class LocationCalculation{
objPos
:
Array
<
CLLocationCoordinate2D
>
,
minMax
:
AreaLatLon
,
exceed180
:
Bool
)
->
Bool
->
Bool
{
var
lUpperCnt
=
0
var
lLowerCnt
=
0
...
...
@@ -525,8 +716,8 @@ class LocationCalculation{
//直線S-E Y=(Ey-Sy)/Ex-Sx)*X+(Sy*Ex-Sx*Ey)/(Ex-Sx)
//交点のY座標、Y
let
Y
=
(
lpEP
.
latitude
-
lpSP
.
latitude
)
/
(
lpEP
.
longitude
-
lpSP
.
longitude
)
*
cx
+
(
lpSP
.
latitude
*
lpEP
.
longitude
-
lpSP
.
longitude
*
lpEP
.
latitude
)
/
(
lpEP
.
longitude
-
lpSP
.
longitude
)
(
lpSP
.
latitude
*
lpEP
.
longitude
-
lpSP
.
longitude
*
lpEP
.
latitude
)
/
(
lpEP
.
longitude
-
lpSP
.
longitude
)
if
lpSP
.
longitude
==
cx
{
//始点が中心線上にある場合
//終点がその前の線分の始点と同じ方向か?
if
(
lpEP
.
longitude
==
maxX
&&
lBeforeLR
==
1
)
...
...
@@ -561,7 +752,7 @@ class LocationCalculation{
}
}
if
lUpperCnt
%
2
==
1
&&
lLowerCnt
%
2
==
1
{
if
lUpperCnt
%
2
==
1
&&
lLowerCnt
%
2
==
1
{
return
true
}
else
{
return
false
...
...
@@ -578,7 +769,7 @@ class LocationCalculation{
minMax
:
AreaLatLon
,
exceed180
:
Bool
,
exceed180Search
:
Bool
)
->
(
first
:
CLLocationCoordinate2D
,
second
:
CLLocationCoordinate2D
)
->
(
first
:
CLLocationCoordinate2D
,
second
:
CLLocationCoordinate2D
)
{
var
maxRt
=
max
var
minRt
=
min
...
...
@@ -633,7 +824,7 @@ class LocationCalculation{
lastPos
:
CLLocationCoordinate2D
,
//レグ起点
nextPos
:
CLLocationCoordinate2D
,
//レグ終点
shipPos
:
CLLocationCoordinate2D
)
//自船位置
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
{
let
deg1
=
bearing
(
lastPos
:
lastPos
,
nextPos
:
nextPos
)
//レグ起点 → レグ終点
let
deg2
=
bearing
(
lastPos
:
lastPos
,
nextPos
:
shipPos
)
//レグ起点 → 自船位置
...
...
@@ -669,7 +860,7 @@ class LocationCalculation{
lastPos
:
CLLocationCoordinate2D
,
//レグ起点
nextPos
:
CLLocationCoordinate2D
,
//レグ終点
shipPos
:
CLLocationCoordinate2D
)
//自船位置
->
Bool
->
Bool
{
var
checkCross
:
Bool
=
false
...
...
@@ -700,7 +891,7 @@ class LocationCalculation{
static
func
checkPolyline
(
objPos
:
Array
<
CLLocationCoordinate2D
>
,
shipPos
:
CLLocationCoordinate2D
)
->
Double
?
->
Double
?
{
var
distance
:
Double
?
let
rtn
=
crossLineDistance
(
objPos
:
objPos
,
shipPos
:
shipPos
)
...
...
@@ -729,7 +920,7 @@ class LocationCalculation{
static
func
crossLineDistance
(
objPos
:
Array
<
CLLocationCoordinate2D
>
,
shipPos
:
CLLocationCoordinate2D
)
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
{
//Loopしているか確認
var
isLoop
=
false
...
...
@@ -776,7 +967,7 @@ class LocationCalculation{
static
func
pointsDistance
(
objPos
:
Array
<
CLLocationCoordinate2D
>
,
shipPos
:
CLLocationCoordinate2D
)
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
{
var
distance
=
10000000.0
var
nearbyPoint
=
0
...
...
@@ -883,7 +1074,7 @@ class LocationCalculation{
lastPos
:
CLLocationCoordinate2D
,
//レグ起点
nextPos
:
CLLocationCoordinate2D
,
//レグ終点
shipPos
:
CLLocationCoordinate2D
)
//自船位置
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
->
(
retCode
:
Bool
,
xte
:
Double
)
//正常終了:true 異常:false 距離[NM]
{
let
rtn1
=
eNvMrdc
(
lastPos
:
lastPos
,
nextPos
:
nextPos
,
type
:
Mrdc
.
E_NV_MRDC_NORMAL
)
print
(
debug
:
"eNvXteRL1
\(
rtn1
)
"
)
...
...
@@ -910,7 +1101,7 @@ class LocationCalculation{
lastPos
:
CLLocationCoordinate2D
,
//前回位置
nextPos
:
CLLocationCoordinate2D
,
//次回位置
type
:
Mrdc
)
//手法 Normal:E_NV_MRDC_NORMAL forAutoSail:E_NV_MRDC_XTE_R
->
ShipPosInf
->
ShipPosInf
{
var
bRng1
=
0.0
var
bRng2
=
0.0
...
...
@@ -945,7 +1136,7 @@ class LocationCalculation{
//同じ位置かチェック
//『前回位置』と『次回位置』の差が0.00001'以下なら同じ位置とみなす
if
((
abs
(
lastPos
.
latitude
-
nextPos
.
latitude
)
<=
errorRange
)
&&
(
abs
(
lastLon
-
nextLon
)
<=
errorRange
))
{
(
abs
(
lastLon
-
nextLon
)
<=
errorRange
))
{
ret
=
ShipPosInf
(
retCode
:
false
,
co1
:
0.0
,
co2
:
180.0
,
dist
:
0.0
)
return
ret
}
...
...
@@ -969,11 +1160,11 @@ class LocationCalculation{
var
bCalc
=
false
switch
type
{
case
Mrdc
.
E_NV_MRDC_XTE_R
:
case
Mrdc
.
E_NV_MRDC_XTE_R
:
if
(
abs
(
rLat1
-
rLat0
)
>
0.0000001
)
{
bCalc
=
true
}
default
:
default
:
if
(
abs
((
abs
(
bRng1
)
-
pidDiv2
))
>=
(
Double
.
pi
/
180.0
))
{
bCalc
=
true
}
...
...
@@ -994,9 +1185,9 @@ class LocationCalculation{
//手法によってずれ量を変える
var
dist01
:
Double
switch
type
{
case
Mrdc
.
E_NV_MRDC_XTE_R
:
case
Mrdc
.
E_NV_MRDC_XTE_R
:
dist01
=
0.00000011
default
:
default
:
//0.11度ずれた緯度の質を求める
dist01
=
(
tan
(
LocationCalculation
.
deg2rad
(
deg
:
0.11
))
*
abs
(
LocationCalculation
.
rad2deg
(
rad
:
dist
)
*
deg2NM
))
/
60.0
}
...
...
@@ -1026,7 +1217,7 @@ class LocationCalculation{
lastPos
:
CLLocationCoordinate2D
,
//前回位置
nextPos
:
CLLocationCoordinate2D
,
//次回位置
type
:
Mrdc
)
//手法 Normal:E_NV_MRDC_NORMAL forAutoSail:E_NV_MRDC_XTE_R
->
DistanceInf
->
DistanceInf
{
var
bRng1
=
0.0
var
dist
=
0.0
...
...
@@ -1060,7 +1251,7 @@ class LocationCalculation{
//同じ位置かチェック
//『前回位置』と『次回位置』の差が0.00001'以下なら同じ位置とみなす
if
((
abs
(
lastPos
.
latitude
-
nextPos
.
latitude
)
<=
errorRange
)
&&
(
abs
(
lastLon
-
nextLon
)
<=
errorRange
))
{
(
abs
(
lastLon
-
nextLon
)
<=
errorRange
))
{
ret
=
DistanceInf
(
retCode
:
false
,
dist
:
dist
)
return
ret
}
...
...
@@ -1084,11 +1275,11 @@ class LocationCalculation{
var
bCalc
=
false
switch
type
{
case
Mrdc
.
E_NV_MRDC_XTE_R
:
case
Mrdc
.
E_NV_MRDC_XTE_R
:
if
(
abs
(
rLat1
-
rLat0
)
>
0.0000001
)
{
bCalc
=
true
}
default
:
default
:
if
(
abs
((
abs
(
bRng1
)
-
pidDiv2
))
>=
(
Double
.
pi
/
180.0
))
{
bCalc
=
true
}
...
...
@@ -1109,9 +1300,9 @@ class LocationCalculation{
//手法によってずれ量を変える
var
dist01
:
Double
switch
type
{
case
Mrdc
.
E_NV_MRDC_XTE_R
:
case
Mrdc
.
E_NV_MRDC_XTE_R
:
dist01
=
0.00000011
default
:
default
:
//0.11度ずれた緯度の質を求める
dist01
=
(
tan
(
LocationCalculation
.
deg2rad
(
deg
:
0.11
))
*
abs
(
LocationCalculation
.
rad2deg
(
rad
:
dist
)
*
deg2NM
))
/
60.0
}
...
...
@@ -1139,7 +1330,7 @@ class LocationCalculation{
static
func
bearing
(
lastPos
:
CLLocationCoordinate2D
,
//前回位置
nextPos
:
CLLocationCoordinate2D
)
//次回位置
->
BearingInf
->
BearingInf
{
var
bRng1
=
0.0
var
bRng2
=
0.0
...
...
@@ -1172,7 +1363,7 @@ class LocationCalculation{
//同じ位置かチェック
//『前回位置』と『次回位置』の差が0.00001'以下なら同じ位置とみなす
if
((
abs
(
lastPos
.
latitude
-
nextPos
.
latitude
)
<=
errorRange
)
&&
(
abs
(
lastLon
-
nextLon
)
<=
errorRange
))
{
(
abs
(
lastLon
-
nextLon
)
<=
errorRange
))
{
ret
=
BearingInf
(
retCode
:
false
,
co1
:
0.0
,
co2
:
180.0
)
return
ret
}
...
...
@@ -1280,13 +1471,392 @@ class LocationCalculation{
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
)
}
/**
* 等角航法での推測位置計算
* 等角航法で始点座標とその方位から任意の距離における位置座標を求める
*
* build/src/ENv/ENv.cpp ENvMrnp移植
*/
static
func
eNvMrnp
(
static
func
eNvMrnp
(
startPos
:
CLLocationCoordinate2D
,
course
:
Double
,
distance
:
Double
...
...
@@ -1321,4 +1891,195 @@ class LocationCalculation{
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
}
}
Seilassist/Sailassist/LocationViewModel.swift
View file @
95aff94d
...
...
@@ -14,6 +14,7 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
private
let
locationManager
:
CLLocationManager
let
ecaTask
=
EcaTask
()
let
ngaTask
=
NgaTask
()
override
init
()
{
let
ecaArea
=
EcaArea
()
...
...
@@ -84,6 +85,7 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
if
Preferences
.
LocationType
==
0
{
ecaTask
.
checkEca
()
ngaTask
.
checkNga
()
}
}
...
...
@@ -91,8 +93,9 @@ class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
if
serverLocationInterval
<=
DateTextLib
.
Date2UnixTime
(
date
:
Date
())
{
let
eca
=
EcaTask
()
eca
.
start
()
self
.
ecaTask
.
checkEca
()
self
.
ngaTask
.
checkNga
()
serverLocationInterval
=
DateTextLib
.
Date2UnixTime
(
date
:
Date
())
+
Int64
(
TimerInterval
)
}
}
...
...
Seilassist/Sailassist/Login/LoginView.swift
View file @
95aff94d
...
...
@@ -221,6 +221,9 @@ struct LoginView: View {
let
ecaList
=
GetEcaList
()
ecaList
.
start
()
let
ngaList
=
GetNgaList
()
ngaList
.
start
()
let
pushHistory
=
GetPushHistory
()
pushHistory
.
start
()
}
...
...
Seilassist/Sailassist/Login/View/InputUserNameView.swift
View file @
95aff94d
...
...
@@ -127,6 +127,9 @@ struct InputUserNameView: View {
let
ecaList
=
GetEcaList
()
ecaList
.
start
()
let
ngaList
=
GetNgaList
()
ngaList
.
start
()
let
pushHistory
=
GetPushHistory
()
pushHistory
.
start
()
}
...
...
Seilassist/Sailassist/Map/LayerEnum.swift
deleted
100644 → 0
View file @
7f096f00
//
// 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
}
Seilassist/Sailassist/Map/MapInformation.swift
0 → 100644
View file @
95aff94d
//
// 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
\n
000°00.000'E"
if
let
shipPos
=
ship
.
location
{
location
=
LocationCalculation
.
locationDegtoString
(
location
:
shipPos
)
}
return
location
}
}
#Preview {
MapInformation
()
}
Seilassist/Sailassist/Map/MapRepresentable.swift
View file @
95aff94d
...
...
@@ -10,8 +10,9 @@ import SwiftUI
import
MapboxMaps
import
UIKit
struct
MapRepresentable
:
UIViewControllerRepresentable
{
struct
MapRepresentable
:
UIViewControllerRepresentable
{
@ObservedObject
var
ecaData
=
SharingData
.
eca
@ObservedObject
var
ngaData
=
SharingData
.
nga
@ObservedObject
var
location
=
SharingData
.
location
@ObservedObject
var
map
=
SharingData
.
map
@ObservedObject
var
pushHistory
=
SharingData
.
pushHistory
...
...
@@ -21,18 +22,18 @@ struct MapRepresentable: UIViewControllerRepresentable{
func
makeUIViewController
(
context
:
Context
)
->
some
UIViewController
{
mapVC
}
//Viewが更新された場合に必要な処理を実装
func
updateUIViewController
(
_
uiViewController
:
UIViewControllerType
,
context
:
Context
)
{
let
ecaArea
=
ecaData
.
ecaArea
.
map
{
$0
.
1
}
.
filter
{
$0
.
isRunning
}
.
first
if
let
ecaArea
=
ecaArea
{
if
let
ecaArea
=
ecaArea
{
mapVC
.
updateEcaLine
(
line
:
ecaArea
.
points
)
}
else
{
mapVC
.
removeEcaLine
()
}
//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
.
updateOneTimeEca
(
eca
:
focusEca
.
points
)
//10秒後削除
...
...
@@ -40,25 +41,35 @@ struct MapRepresentable: UIViewControllerRepresentable{
mapVC
.
updateOneTimeEca
(
eca
:
nil
)
}
}
//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
latitude
=
position
.
lat
,
let
longitude
=
position
.
lon
{
mapVC
.
updateCamera
(
location
:
CLLocationCoordinate2D
(
latitude
:
latitude
,
longitude
:
longitude
),
zoomlevel
:
nil
)
}
}
}
//自船を画面中央に表示
if
location
.
focusOwnShip
{
mapVC
.
updateCamera
(
location
:
location
.
location
,
zoomlevel
:
nil
)
}
if
let
mylocation
=
location
.
location
{
mapVC
.
updateOwnShip
(
location
:
mylocation
,
bearing
:
location
.
heading
)
if
let
ecaArea
=
ecaArea
{
mapVC
.
updateOwnShip
Symbol
(
location
:
mylocation
,
bearing
:
location
.
heading
)
if
let
ecaArea
=
ecaArea
{
mapVC
.
updateEcaSwitchingLine
(
center
:
mylocation
,
notice
:
ecaArea
.
swNotice
,
start
:
ecaArea
.
swStart
,
finish
:
ecaArea
.
swFinish
)
}
else
{
mapVC
.
removeEcaSwitchingLine
()
...
...
@@ -66,26 +77,45 @@ struct MapRepresentable: UIViewControllerRepresentable{
}
mapVC
.
updateWakeLines
(
legLine
:
map
.
legLine
,
portLine
:
map
.
portLine
,
starboardLine
:
map
.
starboardLine
)
mapVC
.
updateWayPoints
(
points
:
map
.
wayPoints
)
mapVC
.
updateEditTarget
()
if
SharingData
.
nga
.
editType
==
EditNgaType
.
addPoint
||
SharingData
.
nga
.
editType
==
EditNgaType
.
movePoint
{
mapVC
.
updateEditArea
(
remove
:
false
)
}
if
SharingData
.
nga
.
editType
==
EditNgaType
.
registered
{
mapVC
.
updateEditArea
(
remove
:
true
)
SharingData
.
nga
.
editType
=
EditNgaType
.
nonEdit
}
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
)
}
if
SharingData
.
map
.
isMapFree
==
true
{
mapVC
.
lockEditPoint
(
isLocked
:
true
)
SharingData
.
map
.
isMapFree
=
false
}
mapVC
.
updateAlertArea
()
}
}
class
MapViewController
:
UIViewController
{
class
MapViewController
:
UIViewController
{
internal
var
mapView
:
MapView
!
var
ownShipSymbol
=
MapSource
(
layer
:
.
OwnShip
)
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
)
internal
var
touchedFeatures
:
Feature
?
=
nil
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
let
centerCoordinate
=
CLLocationCoordinate2D
(
latitude
:
37.8
,
longitude
:
-
96
)
// let url = StyleURI(rawValue: "mapbox://styles/jmarinecloud/cltrwnk5i01j901ra3g4n7dtz")
// let options = MapInitOptions(cameraOptions: CameraOptions(center: centerCoordinate, zoom: 2), styleURI: url)
// 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
))
mapView
=
MapView
(
frame
:
view
.
bounds
,
mapInitOptions
:
options
)
...
...
@@ -93,300 +123,394 @@ class MapViewController : UIViewController{
self
.
view
.
addSubview
(
mapView
)
mapView
.
mapboxMap
.
onNext
(
event
:
.
mapLoaded
)
{
[
self
]
_
in
self
.
addIconImage
()
self
.
addLayers
()
}
//地図上クリック
let
singleTap
=
UITapGestureRecognizer
(
target
:
self
,
action
:
#selector(
handleMapTap(sender:)
)
)
singleTap
.
numberOfTapsRequired
=
1
for
recognizer
in
mapView
.
gestureRecognizers
!
where
recognizer
is
UITapGestureRecognizer
{
singleTap
.
require
(
toFail
:
recognizer
)
}
singleTap
.
numberOfTouchesRequired
=
1
//下記処理を加えると動作しない
// for recognizer in mapView.gestureRecognizers! where recognizer is UITapGestureRecognizer {
// singleTap.require(toFail: recognizer)
// }
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:)
)
)
for
recognizer
in
mapView
.
gestureRecognizers
!
where
recognizer
is
UILongPressGestureRecognizer
{
longPress
.
require
(
toFail
:
recognizer
)
}
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
)
{
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
)
// mapboxMapManager.targetInfo = nil
// guard let touchedFeature = mapboxMapManager?.mapClick(pos: spot) else { return }
// // 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
// }
// }
let
coordinate
=
mapView
.
mapboxMap
.
coordinate
(
for
:
spot
)
mapClick
(
point
:
spot
,
coordinate
:
coordinate
)
}
/**
* 地図上長押しアクション
*/
@objc
func
handleMapLongPress
(
sender
:
UILongPressGestureRecognizer
){
print
(
debug
:
"calld"
)
// // AIS情報問い合わせ
// //if SharingData.Vessels.distantTimer <= 0 { // 現在表示中でない
// // 長押し位置の緯度経度を得る
// 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
handleMapLongPress
(
sender
:
UILongPressGestureRecognizer
)
{
let
spot
=
sender
.
location
(
in
:
mapView
)
let
coordinate
=
mapView
.
mapboxMap
.
coordinate
(
for
:
spot
)
mapLongClick
(
point
:
spot
,
coordinate
:
coordinate
)
}
/**
* 地図上ドラッグアクション
*/
@objc
func
handleMapDrug
(
sender
:
UIPanGestureRecognizer
){
print
(
debug
:
"calld"
)
// if let id = SharingData.UserMark.selectedPointId,
// let point = SharingData.UserMark.selectedPointInfo{
// let pos = sender.location(in: mapView)
// let newLocation = mapView.convert(pos, toCoordinateFrom: nil)
// if sender.state == .began{
// guard let touchedFeature = mapboxMapManager.mapClick(pos: pos) else { return }
// guard let type = touchedFeature.attribute(forKey: MapboxMapManager.PropertyKey.ObjectType.rawValue) as? String else { return }
// if let _ = touchedFeature.attribute(forKey: MapboxMapManager.PropertyKey.Id.rawValue) as? Int64,
// type == MapboxMapManager.DataType.UserMark.rawValue &&
// id == SharingData.UserMark.selectedPointId{
// SharingData.UserMark.movePointLocation = newLocation
// }
// }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
)
}
if
let
image
=
UIImage
(
named
:
"swNoticeBack"
){
try
mapView
.
mapboxMap
.
style
.
addImage
(
image
,
id
:
IconImage
.
SwNoticeBack
.
rawValue
)
}
if
let
image
=
UIImage
(
named
:
"swStartBack"
){
try
mapView
.
mapboxMap
.
style
.
addImage
(
image
,
id
:
IconImage
.
SwStartBack
.
rawValue
)
@objc
func
handleMapDrug
(
sender
:
UIPanGestureRecognizer
)
{
let
spot
=
sender
.
location
(
in
:
mapView
)
let
coordinate
=
mapView
.
mapboxMap
.
coordinate
(
for
:
spot
)
print
(
debug
:
"test: handleMapDrug
\(
coordinate
)
"
)
mapDrug
(
point
:
spot
,
coordinate
:
coordinate
)
if
SharingData
.
nga
.
editType
==
EditNgaType
.
movePoint
{
if
let
nga
=
SharingData
.
nga
.
editNga
,
let
no
=
SharingData
.
nga
.
selectPoint
{
var
ngaData
=
nga
ngaData
.
points
[
no
]
=
coordinate
SharingData
.
nga
.
targetLocation
=
coordinate
SharingData
.
nga
.
editNga
=
ngaData
updateEditArea
()
}
if
let
image
=
UIImage
(
named
:
"swFinishBack"
){
try
mapView
.
mapboxMap
.
style
.
addImage
(
image
,
id
:
IconImage
.
SwFinisheBack
.
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
}
struct
IconImageData
{
var
name
:
String
var
id
:
String
}
func
addIconImage
()
{
do
{
for
iconData
in
IconImageList
{
if
let
iconImage
=
UIImage
(
named
:
iconData
.
name
)
{
try
mapView
.
mapboxMap
.
style
.
addImage
(
iconImage
,
id
:
iconData
.
id
)
}
}
}
catch
{
print
(
debug
:
"called"
)
}
}
func
addLayers
(){
addImage
()
//自船
/**
* レイヤー処理
*/
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
}
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
))
ownShipSymbol
.
source
.
data
=
.
feature
(
Feature
(
geometry
:
point
))
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ownShipSymbol
.
source
,
id
:
ownShipSymbol
.
sourceId
)
var
ownShipSymbolLayer
=
SymbolLayer
(
id
:
ownShipSymbol
.
layerId
)
ownShipSymbolLayer
.
source
=
ownShipSymbol
.
sourceId
ownShipSymbolLayer
.
iconImage
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
IconImage
.
rawValue
})
ownShipSymbolLayer
.
iconImage
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
IconImage
.
rawValue
})
ownShipSymbolLayer
.
iconRotationAlignment
=
.
constant
(
.
map
)
ownShipSymbolLayer
.
iconAllowOverlap
=
.
constant
(
true
)
ownShipSymbolLayer
.
iconIgnorePlacement
=
.
constant
(
true
)
ownShipSymbolLayer
.
iconRotate
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Bearing
.
rawValue
})
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ownShipSymbol
.
source
,
id
:
ownShipSymbol
.
sourceId
)
ownShipSymbolLayer
.
iconRotate
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Bearing
.
rawValue
})
try
?
mapView
.
mapboxMap
.
style
.
addLayer
(
ownShipSymbolLayer
)
}
//ECA
/**
* ECAライン表示レイヤー
*/
private
func
ecaLineLayer
()
{
let
ecaLineString
=
LineString
([
LocationCoordinate2D
(
latitude
:
0
,
longitude
:
0
)])
let
ecaLinefeature
=
Feature
(
geometry
:
ecaLineString
)
ecaLine
.
source
.
data
=
.
feature
(
ecaLinefeature
)
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ecaLine
.
source
,
id
:
ecaLine
.
sourceId
)
var
ecaLineLayer
=
LineLayer
(
id
:
ecaLine
.
layerId
)
ecaLineLayer
.
source
=
ecaLine
.
sourceId
ecaLineLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
ecaLineLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
ecaLineLayer
.
lineDasharray
=
.
constant
([
2
,
1
])
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ecaLine
.
source
,
id
:
ecaLine
.
sourceId
)
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
)
oneTimeEca
.
source
.
data
=
.
feature
(
oneTimeEcaLinefeature
)
try!
mapView
.
mapboxMap
.
style
.
addSource
(
oneTimeEca
.
source
,
id
:
oneTimeEca
.
sourceId
)
var
oneTimeEcaLayer
=
LineLayer
(
id
:
oneTimeEca
.
layerId
)
oneTimeEcaLayer
.
source
=
oneTimeEca
.
sourceId
oneTimeEcaLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
oneTimeEcaLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
oneTimeEcaLayer
.
lineDasharray
=
.
constant
([
2
,
1
])
try!
mapView
.
mapboxMap
.
style
.
addSource
(
oneTimeEca
.
source
,
id
:
oneTimeEca
.
sourceId
)
try
?
mapView
.
mapboxMap
.
style
.
addLayer
(
oneTimeEcaLayer
)
//
}
/**
* ECA切替ライン表示レイヤー
*/
private
func
ecaSwitchingLineLayer
()
{
ecaSwitchingLine
.
source
.
data
=
.
featureCollection
(
FeatureCollection
(
features
:
[]))
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ecaSwitchingLine
.
source
,
id
:
ecaSwitchingLine
.
sourceId
)
var
ecaSwitchingLineLayer
=
LineLayer
(
id
:
ecaSwitchingLine
.
layerId
)
ecaSwitchingLineLayer
.
source
=
ecaSwitchingLine
.
sourceId
ecaSwitchingLineLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
ecaSwitchingLineLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
ecaSwitchingLineLayer
.
lineDasharray
=
.
constant
([
2
,
1
])
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ecaSwitchingLine
.
source
,
id
:
ecaSwitchingLine
.
sourceId
)
try
?
mapView
.
mapboxMap
.
style
.
addLayer
(
ecaSwitchingLineLayer
)
//ECA ラベル
}
/**
* ECA切替ラインラベル表示レイヤー
*/
private
func
ecaSwitchingLineLabelLayer
()
{
ecaSwLineLabel
.
source
.
data
=
.
featureCollection
(
FeatureCollection
(
features
:
[]))
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ecaSwLineLabel
.
source
,
id
:
ecaSwLineLabel
.
sourceId
)
var
ecaSwLabelLayer
=
SymbolLayer
(
id
:
ecaSwLineLabel
.
layerId
)
ecaSwLabelLayer
.
source
=
ecaSwLineLabel
.
sourceId
ecaSwLabelLayer
.
textField
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Text
.
rawValue
})
ecaSwLabelLayer
.
iconImage
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
IconImage
.
rawValue
})
ecaSwLabelLayer
.
iconColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
ecaSwLabelLayer
.
textField
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Text
.
rawValue
})
ecaSwLabelLayer
.
iconImage
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
IconImage
.
rawValue
})
ecaSwLabelLayer
.
iconColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
ecaSwLabelLayer
.
iconTextFit
=
.
constant
(
.
both
)
ecaSwLabelLayer
.
iconTextFitPadding
=
.
constant
([
0
,
6
,
0
,
6
])
try!
mapView
.
mapboxMap
.
style
.
addSource
(
ecaSwLineLabel
.
source
,
id
:
ecaSwLineLabel
.
sourceId
)
try
?
mapView
.
mapboxMap
.
style
.
addLayer
(
ecaSwLabelLayer
)
//航路
}
/**
* 航跡ラインレイヤー
*/
private
func
wakeLineLayer
()
{
wakeLines
.
source
.
data
=
.
featureCollection
(
FeatureCollection
(
features
:
[]))
try!
mapView
.
mapboxMap
.
style
.
addSource
(
wakeLines
.
source
,
id
:
wakeLines
.
sourceId
)
var
wakeLineLayer
=
LineLayer
(
id
:
wakeLines
.
layerId
)
wakeLineLayer
.
source
=
wakeLines
.
sourceId
wakeLineLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
try!
mapView
.
mapboxMap
.
style
.
addSource
(
wakeLines
.
source
,
id
:
wakeLines
.
sourceId
)
wakeLineLayer
.
lineColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
try
?
mapView
.
mapboxMap
.
style
.
addLayer
(
wakeLineLayer
)
//WayPoint
}
/**
* wayポイントレイヤー
*/
private
func
wayPointsLayer
()
{
wayPoints
.
source
.
data
=
.
featureCollection
(
FeatureCollection
(
features
:
[]))
try!
mapView
.
mapboxMap
.
style
.
addSource
(
wayPoints
.
source
,
id
:
wayPoints
.
sourceId
)
var
wayPointsLayer
=
SymbolLayer
(
id
:
wayPoints
.
layerId
)
wayPointsLayer
.
source
=
wayPoints
.
sourceId
wayPointsLayer
.
iconImage
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
IconImage
.
rawValue
})
wayPointsLayer
.
iconColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
try!
mapView
.
mapboxMap
.
style
.
addSource
(
wayPoints
.
source
,
id
:
wayPoints
.
sourceId
)
wayPointsLayer
.
iconImage
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
IconImage
.
rawValue
})
wayPointsLayer
.
iconColor
=
.
expression
(
Exp
(
.
get
)
{
PropertyKey
.
Color
.
rawValue
})
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
{
var
shipIcon
=
IconImage
.
OwnShip_Normal
.
rawValue
...
...
@@ -417,31 +541,15 @@ class MapViewController : UIViewController{
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
.
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
){
/**
* ECA表示
*/
func
updateEcaSwitchingLine
(
center
:
CLLocationCoordinate2D
,
notice
:
Float
,
start
:
Float
,
finish
:
Float
)
{
do
{
var
switchingLines
:
[
Feature
]
=
[]
var
switchingLabels
:
[
Feature
]
=
[]
let
circlePoints_notice
=
getCirclePoints
(
center
:
center
,
radiusKm
:
LocationCalculation
.
nm2km
(
nm
:
Double
(
notice
)))
var
noticeLine
=
Feature
(
geometry
:
LineString
(
circlePoints_notice
))
noticeLine
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#62AB28"
)]
...
...
@@ -449,12 +557,11 @@ class MapViewController : UIViewController{
if
let
point
=
circlePoints_notice
.
first
{
var
label
=
Feature
(
geometry
:
Point
(
point
))
label
.
properties
=
[
PropertyKey
.
Text
.
rawValue
:
.
string
(
"Advance Notice"
),
PropertyKey
.
IconImage
.
rawValue
:
.
string
(
IconImage
.
SwNoticeBack
.
rawValue
),
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#62AB28"
)]
PropertyKey
.
IconImage
.
rawValue
:
.
string
(
IconImage
.
SwNoticeBack
.
rawValue
),
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#62AB28"
)]
switchingLabels
.
append
(
label
)
}
let
circlePoints_start
=
getCirclePoints
(
center
:
center
,
radiusKm
:
LocationCalculation
.
nm2km
(
nm
:
Double
(
start
)))
var
startLine
=
Feature
(
geometry
:
LineString
(
circlePoints_start
))
startLine
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#ECD932"
)]
...
...
@@ -462,11 +569,11 @@ class MapViewController : UIViewController{
if
let
point
=
circlePoints_start
.
first
{
var
label
=
Feature
(
geometry
:
Point
(
point
))
label
.
properties
=
[
PropertyKey
.
Text
.
rawValue
:
.
string
(
"Switching Start"
),
PropertyKey
.
IconImage
.
rawValue
:
.
string
(
IconImage
.
SwStartBack
.
rawValue
),
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#ECD932"
)]
PropertyKey
.
IconImage
.
rawValue
:
.
string
(
IconImage
.
SwStartBack
.
rawValue
),
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#ECD932"
)]
switchingLabels
.
append
(
label
)
}
let
circlePoints_finish
=
getCirclePoints
(
center
:
center
,
radiusKm
:
LocationCalculation
.
nm2km
(
nm
:
Double
(
finish
)))
var
finishLine
=
Feature
(
geometry
:
LineString
(
circlePoints_finish
))
finishLine
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#EF6135"
)]
...
...
@@ -474,19 +581,24 @@ class MapViewController : UIViewController{
if
let
point
=
circlePoints_finish
.
first
{
var
label
=
Feature
(
geometry
:
Point
(
point
))
label
.
properties
=
[
PropertyKey
.
Text
.
rawValue
:
.
string
(
"Switching Finish"
),
PropertyKey
.
IconImage
.
rawValue
:
.
string
(
IconImage
.
SwFinisheBack
.
rawValue
),
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#EF6135"
)]
PropertyKey
.
IconImage
.
rawValue
:
.
string
(
IconImage
.
SwFinisheBack
.
rawValue
),
PropertyKey
.
Color
.
rawValue
:
.
string
(
"#EF6135"
)]
switchingLabels
.
append
(
label
)
}
let
lineGeoJson
=
FeatureCollection
(
features
:
switchingLines
)
let
labelGeoJson
=
FeatureCollection
(
features
:
switchingLabels
)
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaSwitchingLine
.
sourceId
,
geoJSON
:
.
featureCollection
(
lineGeoJson
))
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaSwLineLabel
.
sourceId
,
geoJSON
:
.
featureCollection
(
labelGeoJson
))
}
catch
{}
}
catch
{
print
(
debug
:
"called"
)
}
}
func
removeEcaSwitchingLine
(){
/**
* ECA消去
*/
func
removeEcaSwitchingLine
()
{
do
{
let
switchingLines
:
[
Feature
]
=
[]
let
switchingLabels
:
[
Feature
]
=
[]
...
...
@@ -495,71 +607,419 @@ class MapViewController : UIViewController{
let
labelGeoJson
=
FeatureCollection
(
features
:
switchingLabels
)
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaSwitchingLine
.
sourceId
,
geoJSON
:
.
featureCollection
(
lineGeoJson
))
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaSwLineLabel
.
sourceId
,
geoJSON
:
.
featureCollection
(
labelGeoJson
))
}
catch
{}
}
///円の位置情報を返す
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
)
}
catch
{
print
(
debug
:
"called"
)
}
return
circlePoints
}
func
updateEcaLine
(
line
:
[
CLLocationCoordinate2D
]){
/**
* ECAライン更新
*/
func
updateEcaLine
(
line
:
[
CLLocationCoordinate2D
])
{
do
{
var
geoJson
=
Feature
(
geometry
:
LineString
(
line
))
geoJson
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
Color
.
blue
.
description
)]
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaLine
.
sourceId
,
geoJSON
:
.
feature
(
geoJson
))
}
catch
{}
}
catch
{
print
(
debug
:
"called"
)
}
}
/**
* ECAライン消去
*/
func
removeEcaLine
(){
do
{
let
line
:
[
CLLocationCoordinate2D
]
=
[]
let
geoJson
=
Feature
(
geometry
:
LineString
(
line
))
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaLine
.
sourceId
,
geoJSON
:
.
feature
(
geoJson
))
}
catch
{}
}
catch
{
print
(
debug
:
"called"
)
}
}
///一時的に見たいEcaを表示
func
updateOneTimeEca
(
eca
:
[
CLLocationCoordinate2D
]?){
do
{
func
updateOneTimeEca
(
eca
:
[
CLLocationCoordinate2D
]?)
{
do
{
let
eca
=
eca
??
[]
var
geoJson
=
Feature
(
geometry
:
LineString
(
eca
))
geoJson
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
Color
.
black
.
description
)]
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
{
var
legLineFeature
=
Feature
(
geometry
:
LineString
(
legLine
))
legLineFeature
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
Color
.
blue
.
description
)]
var
portLineFeature
=
Feature
(
geometry
:
LineString
(
portLine
))
portLineFeature
.
properties
=
[
PropertyKey
.
Color
.
rawValue
:
.
string
(
Color
.
blue
.
description
)]
var
starboardLineFeature
=
Feature
(
geometry
:
LineString
(
starboardLine
))
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
])))
}
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"
)
}
}
///子午線を跨ぐ位置情報をチェックして東経ベースに補正する。
static
func
checkStraddleMeridian
(
_
locations
:
[
CLLocationCoordinate2D
])
->
[
CLLocationCoordinate2D
]{
/**
* カメラ
*/
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
]
{
let
eastLon
=
FloatingPointSign
.
plus
var
returnLocations
:
[
CLLocationCoordinate2D
]
=
[]
for
location
in
locations
{
...
...
@@ -571,44 +1031,237 @@ class MapViewController : UIViewController{
returnLocations
.
append
(
location
)
}
}
return
returnLocations
}
func
updateWayPoints
(
points
:
[
CLLocationCoordinate2D
]){
do
{
var
wayPointsFeatures
:
[
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"
)]
wayPointsFeatures
.
append
(
feature
)
}
try
self
.
mapView
.
mapboxMap
.
style
.
updateGeoJSONSource
(
withId
:
ecaSwLineLabel
.
sourceId
,
geoJSON
:
.
featureCollection
(
FeatureCollection
(
features
:
wayPointsFeatures
)))
}
catch
{}
/**
* 円の位置情報を返す
*/
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
}
enum
PropertyKey
:
String
{
case
Id
case
Dtype
case
IconImage
case
Bearing
case
Color
case
Text
case
Size
case
LineWidth
case
FillOpacity
case
FillOutlineColor
}
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
enum
DataType
:
String
{
case
ownShip
case
point
case
line
case
add
}
}
/**
* 地図上クリック
*/
func
mapClick
(
point
:
CGPoint
,
coordinate
:
CLLocationCoordinate2D
)
{
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
)
}
}
}
Seilassist/Sailassist/Map/MapSource.swift
View file @
95aff94d
...
...
@@ -13,7 +13,7 @@ struct MapSource {
let
layerId
:
String
var
source
=
GeoJSONSource
()
init
(
layer
:
LayerEnum
)
{
init
(
layer
:
MapViewController
.
LayerEnum
)
{
sourceId
=
layer
.
rawValue
+
"Source"
layerId
=
layer
.
rawValue
+
"Layer"
}
...
...
Seilassist/Sailassist/Map/Task/View/EcaListView.swift
View file @
95aff94d
...
...
@@ -26,9 +26,9 @@ struct EcaListView: View {
var
newData
=
eca
newData
.
isEnable
.
toggle
()
ecaData
.
editEcaArea
(
key
:
eca
.
areaId
,
value
:
newData
,
type
:
EcaOperation
.
Insert
)
taskViewModel
.
viewMode
=
.
SwitchingMenu
taskViewModel
.
viewMode
=
.
FuelSwitching
taskViewModel
.
edittingEcaArea
=
eca
taskViewModel
.
isShowSettingView
=
true
taskViewModel
.
viewMode
=
.
EcaSetting
},
label
:
{
Image
(
"icon_plus"
)
.
resizable
()
...
...
Seilassist/Sailassist/Map/Task/View/EcaSettingView.swift
View file @
95aff94d
...
...
@@ -9,10 +9,9 @@ import SwiftUI
import
UIKit
struct
EcaSettingView
:
View
{
// @ObservedObject var taskViewModel: TaskViewModel
@Binding
var
isShowSettingEca
:
Bool
@ObservedObject
var
taskViewModel
:
TaskViewModel
@State
var
edittingEca
:
RegisteredEca
var
body
:
some
View
{
VStack
(
spacing
:
0
){
SwSliderView
(
data
:
$
edittingEca
,
type
:
.
Finish
)
...
...
@@ -40,7 +39,6 @@ struct EcaSettingView: View {
var
ecaData
=
edittingEca
ecaData
.
isEnable
=
true
SharingData
.
eca
.
editEcaArea
(
key
:
edittingEca
.
areaId
,
value
:
ecaData
,
type
:
EcaOperation
.
Change
)
isShowSettingEca
=
false
},
label
:
{
Text
(
"Register"
)
.
font
(
FontStyle
.
DefaultText
.
font
)
...
...
@@ -59,7 +57,7 @@ struct EcaSettingView: View {
let
notice
=
edittingEca
.
swNotice
let
start
=
edittingEca
.
swStart
let
finish
=
edittingEca
.
swFinish
return
notice
>
start
&&
notice
>
finish
&&
start
>
finish
}
...
...
@@ -213,5 +211,5 @@ struct EcaSettingView: View {
}
#Preview {
EcaSettingView
(
isShowSettingEca
:
.
constant
(
true
),
edittingEca
:
RegisteredEca
(
id
:
0
,
ecaName
:
"ec
a"
)
!
)
EcaSettingView
(
taskViewModel
:
TaskViewModel
(),
edittingEca
:
RegisteredEca
(
id
:
0
,
areaName
:
"Alert Are
a"
)
!
)
}
Seilassist/Sailassist/Map/Task/View/
TaskSwitchingMenu
View.swift
→
Seilassist/Sailassist/Map/Task/View/
FuelSwitching
View.swift
View file @
95aff94d
//
//
TaskSwitchingMenu
View.swift
//
FuelSwitching
View.swift
// forShip
//
// Created by Mamoru Sugita on 2023/10/18.
...
...
@@ -7,7 +7,7 @@
import
SwiftUI
struct
TaskSwitchingMenu
View
:
View
{
struct
FuelSwitching
View
:
View
{
@ObservedObject
var
taskViewModel
:
TaskViewModel
@ObservedObject
var
ecaData
=
SharingData
.
eca
@State
var
isDeleteAlert
:
Bool
=
false
...
...
@@ -57,7 +57,7 @@ struct TaskSwitchingMenuView: View {
Button
{
taskViewModel
.
edittingEcaArea
=
eca
taskViewModel
.
ecaName
=
eca
.
name
taskViewModel
.
isShowSettingView
=
true
taskViewModel
.
viewMode
=
.
EcaSetting
}
label
:
{
Text
(
"Edit Notice Setting"
)
}
...
...
@@ -102,15 +102,6 @@ struct TaskSwitchingMenuView: View {
taskViewModel
.
edittingEcaArea
=
nil
}
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
:
{
Text
(
"Have you finished "
+
taskViewModel
.
ecaName
+
" fuel switching?"
)
}
...
...
@@ -137,11 +128,10 @@ struct TaskSwitchingMenuView: View {
Spacer
()
}
// .padding()
}
}
#Preview {
TaskSwitchingMenu
View
(
taskViewModel
:
TaskViewModel
())
FuelSwitching
View
(
taskViewModel
:
TaskViewModel
())
}
Seilassist/Sailassist/Map/Task/View/MapTaskView.swift
deleted
100644 → 0
View file @
7f096f00
//
// 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?
\n
If you finish, you disable it."
)
case
.
incomplete
:
Text
(
"Have you finished
\(
ecaArea
.
name
)
fuel switching?
\n
If you finish, you disable it."
)
default
:
Text
(
""
)
}
}
}
}
}
}
#Preview {
MapTaskView
()
}
Seilassist/Sailassist/Map/Task/View/MenuTaskView.swift
0 → 100644
View file @
95aff94d
//
// 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?
\n
If you finish, you disable it."
)
case
.
incomplete
:
Text
(
"Have you finished
\(
ecaArea
.
name
)
fuel switching?
\n
If 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
())
}
Seilassist/Sailassist/Map/Task/View/NgaNotificationView.swift
0 → 100644
View file @
95aff94d
//
// 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
())
}
Seilassist/Sailassist/Map/Task/View/NgaSettingView.swift
0 → 100644
View file @
95aff94d
//
// 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
())
}
Seilassist/Sailassist/Map/Task/ViewModel/TaskViewModel.swift
View file @
95aff94d
...
...
@@ -8,8 +8,8 @@
import
Foundation
class
TaskViewModel
:
ObservableObject
{
@Published
var
viewMode
:
TaskViewMode
=
.
SwitchingMenu
@Published
var
viewMode
:
TaskViewMode
=
.
MenuList
@Published
var
edittingEcaArea
:
RegisteredEca
?
=
nil
@Published
var
ecaName
:
String
=
""
@Published
var
isShowSettingView
:
Bool
=
false
@Published
var
ngaName
:
String
=
""
}
Seilassist/Sailassist/Menu/View/MenuTitleView.swift
View file @
95aff94d
...
...
@@ -10,7 +10,7 @@ import SwiftUI
struct
MenuTitleView
:
View
{
@Binding
var
path
:
[
MenuPath
]
var
title
=
"Menu"
var
title
=
"Menu
Functions
"
var
body
:
some
View
{
VStack
{
HStack
{
...
...
Seilassist/Sailassist/NGA/DeleteNgaArea.swift
0 → 100644
View file @
95aff94d
//
// 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
}
}
}
Seilassist/Sailassist/NGA/GetNgaList.swift
0 → 100644
View file @
95aff94d
//
// 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
}
}
}
Seilassist/Sailassist/NGA/NgaTask.swift
0 → 100644
View file @
95aff94d
//
// 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
)
}
}
}
}
}
}
}
Seilassist/Sailassist/NGA/RegistereNga.swift
0 → 100644
View file @
95aff94d
//
// 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
}
}
Seilassist/Sailassist/NGA/SetNgaArea.swift
0 → 100644
View file @
95aff94d
//
// 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
}
}
}
Seilassist/Sailassist/ServerSession/ServerSession.swift
View file @
95aff94d
...
...
@@ -211,32 +211,29 @@ class ServerSession{
func
httpBody
(
boundary
:
String
,
_
uploadImage
:
ReqUploadImage
)
->
Data
!
{
var
httpBody1
=
"--
\(
boundary
)\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
s
hipId
\"\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
S
hipId
\"\r\n
"
httpBody1
+=
"
\r\n
"
httpBody1
+=
"
\(
uploadImage
.
shipId
)\r\n
"
httpBody1
+=
"--
\(
boundary
)\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
m
essageId
\"\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
M
essageId
\"\r\n
"
httpBody1
+=
"
\r\n
"
httpBody1
+=
"
\(
uploadImage
.
messageId
)\r\n
"
httpBody1
+=
"--
\(
boundary
)\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
l
ocation
\"\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
L
ocation
\"\r\n
"
httpBody1
+=
"
\r\n
"
httpBody1
+=
"
\(
uploadImage
.
location
)\r\n
"
httpBody1
+=
"--
\(
boundary
)\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
f
rom
\"\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
F
rom
\"\r\n
"
httpBody1
+=
"
\r\n
"
httpBody1
+=
"
\(
uploadImage
.
from
)\r\n
"
httpBody1
+=
"--
\(
boundary
)\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
f
romId
\"\r\n
"
httpBody1
+=
"Content-Disposition: form-data; name=
\"
F
romId
\"\r\n
"
httpBody1
+=
"
\r\n
"
httpBody1
+=
"
\(
uploadImage
.
fromId
)\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
+=
"
\r\n
"
// var tmp = httpBody1.data(using: .utf8)!
var
httpBody
=
Data
()
httpBody
.
append
(
httpBody1
.
data
(
using
:
.
utf8
)
!
)
httpBody
.
append
(
uploadImage
.
files
)
...
...
Seilassist/Sailassist/ServerSession/SessionNgaList.swift
0 → 100644
View file @
95aff94d
//
// 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
)
}
}
}
Seilassist/Sailassist/ServerSession/SessionUploadImage.swift
View file @
95aff94d
...
...
@@ -33,8 +33,7 @@ class SessionUploadImage : ObservableObject {
return
}
// let boundary = "----------" + UUID().uuidString
let
boundary
=
"----WebKitFormBoundaryZLdHZy8HNaBmUX0d"
let
boundary
=
"----------"
+
uploadImage
.
messageId
if
let
postdata
=
serverSession
.
httpBody
(
boundary
:
boundary
,
uploadImage
)
{
serverSession
.
postForm
(
boundary
:
boundary
,
req_url
,
postdata
,
completion
:
completion
)
}
...
...
Seilassist/Sailassist/SharingData/SharingData.swift
View file @
95aff94d
...
...
@@ -8,7 +8,7 @@ import Foundation
import
CoreLocation
class
SharingData
{
static
var
my
=
My
()
class
My
:
ObservableObject
{
@Published
var
id
:
Int
=
0
...
...
@@ -112,23 +112,7 @@ class SharingData{
@Published
var
legLine
:
[
CLLocationCoordinate2D
]
=
[]
@Published
var
portLine
:
[
CLLocationCoordinate2D
]
=
[]
@Published
var
starboardLine
:
[
CLLocationCoordinate2D
]
=
[]
}
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
]
=
[]
@Published
var
isMapFree
:
Bool
=
false
}
/**
...
...
@@ -139,7 +123,7 @@ class SharingData{
@Published
var
ecaArea
:
Dictionary
<
Int
,
RegisteredEca
>
=
[:]
@Published
var
focusEca
:
Int
?
=
nil
@Published
var
isShowEcaAlert
:
Bool
=
false
func
setEcaArea
(
key
:
Int
,
value
:
RegisteredEca
)
{
ecaArea
.
updateValue
(
value
,
forKey
:
key
)
}
...
...
@@ -218,7 +202,7 @@ class SharingData{
task
.
status
=
setEcaStatus
(
eca
:
value
)
}
setEcaArea
.
start
(
eca
:
task
)
case
EcaOperation
.
Cancel
:
case
EcaOperation
.
Cancel
:
task
.
areaId
=
value
.
areaId
task
.
taskName
=
value
.
name
task
.
noticeRange
=
value
.
swNotice
...
...
@@ -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
()
class
PushHistory
:
ObservableObject
{
@Published
var
pushHistoryData
:
Dictionary
<
Int
,
ResPushHistory
>
=
[:]
...
...
Seilassist/Sailassist/SharingData/StatusEnum.swift
View file @
95aff94d
...
...
@@ -20,6 +20,14 @@ enum EcaOperation {
case
Cancel
}
enum
NgaOperation
{
case
Change
case
Delete
case
Running
case
Cancel
case
Passing
}
enum
ShipAlert
{
case
Offline
case
Unknown
...
...
Seilassist/Sailassist/Tab/MainTabView.swift
View file @
95aff94d
...
...
@@ -8,8 +8,8 @@
import
SwiftUI
enum
Tab
:
String
,
CaseIterable
{
case
chat
=
"tab_chat"
case
task
=
"tab_task"
case
chat
=
"tab_chat"
case
alert
=
"tab_notification"
case
menu
=
"tab_menu"
...
...
@@ -41,9 +41,12 @@ struct MainTabView: View {
ChatView
()
.
tag
(
Tab
.
chat
)
MapRepresentable
()
.
ignoresSafeArea
()
.
tag
(
Tab
.
task
)
ZStack
{
MapRepresentable
()
MapInformation
()
}
.
ignoresSafeArea
()
.
tag
(
Tab
.
task
)
NotificationView
()
.
tag
(
Tab
.
alert
)
...
...
@@ -53,7 +56,7 @@ struct MainTabView: View {
}
.
hideNativeTabBar
()
.
sheet
(
isPresented
:
.
constant
(
isTaskSel
&&
isTabShow
&&
SharingData
.
my
.
isFuelSwitchTask
),
content
:
{
M
ap
TaskView
()
M
enu
TaskView
()
.
zIndex
(
0
)
.
presentationDragIndicator
(
.
hidden
)
.
presentationDetents
([
.
height
(
150
),
.
medium
,
.
fraction
(
0.99
)])
...
...
@@ -81,7 +84,7 @@ struct MainTabView: View {
}
.
hideNativeTabBar
()
.
popover
(
isPresented
:
.
constant
(
isPopover
&&
SharingData
.
my
.
isFuelSwitchTask
),
attachmentAnchor
:
.
point
(
.
bottom
))
{
M
ap
TaskView
()
M
enu
TaskView
()
.
presentationCompactAdaptation
(
.
none
)
.
zIndex
(
0
)
.
frame
(
minWidth
:
300
,
maxHeight
:
500
)
...
...
Seilassist/Sailassist/VoiceManager/AlertManager.swift
View file @
95aff94d
...
...
@@ -19,10 +19,6 @@ class AlertManager {
var
lastSpeech
:
String
=
""
// 警報を鳴らす。引数の型定義はAlertDB.swift
func
VocalizeAlert
(
alertrec
:
WarnRecord
)
{
VocalizeAlert
(
alertrec
:
alertrec
,
identifier
:
.
EcaSwitching
)
}
func
VocalizeAlert
(
alertrec
:
WarnRecord
,
identifier
:
PushNotificationTypes
.
LocalPushIdentifier
)
{
print
(
debug
:
"alertrec =
\(
alertrec
)
"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment