Skip to content

Commit 16ae380

Browse files
committed
laylines
1 parent 0510d75 commit 16ae380

File tree

8 files changed

+127
-111
lines changed

8 files changed

+127
-111
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
- **Added**: Setting to mute all sounds regardless of notification ALARM_METHOD value.(#178)
77
- **Updated**: Show total length of Route when editing. (#171)
88
- **Added**: Toggle charts on/of by clicking chart boundaries on map.
9+
- **Added**: Lock in `Follow Vessel` setting to remain in this mode when map is panned. (#185)
10+
- **Fixed**: Not rendering laylines when preferred path is `environment.wind.directionMagnetic`. (#184)
911

1012
### v2.11.1
1113

src/app/app.settings.ts

Lines changed: 6 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,6 @@ export function cleanConfig(
5353
settings.selections.vessel.aisCogLine = 10;
5454
}
5555

56-
// changeover 2.7 - for removal
57-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
58-
if (typeof (settings as any).vesselTrail !== 'undefined') {
59-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
60-
settings.selections.vessel.trail = (settings as any).vesselTrail;
61-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
62-
delete (settings as any).vesselTrail;
63-
}
64-
// changeover 2.7 - for removal
65-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
66-
if (typeof (settings as any).vesselWindVectors !== 'undefined') {
67-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
68-
settings.selections.vessel.windVectors = (
69-
settings as any
70-
).vesselWindVectors;
71-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
72-
delete (settings as any).vesselWindVectors;
73-
}
74-
7556
if (typeof settings.map.limitZoom === 'undefined') {
7657
settings.map.limitZoom = false;
7758
}
@@ -80,6 +61,10 @@ export function cleanConfig(
8061
settings.map.invertColor = false;
8162
}
8263

64+
if (typeof settings.map.lockMoveMap === 'undefined') {
65+
settings.map.lockMoveMap = false;
66+
}
67+
8368
if (typeof settings.anchorRadius === 'undefined') {
8469
settings.anchorRadius = 40;
8570
}
@@ -100,15 +85,6 @@ export function cleanConfig(
10085
settings.selections.labelsMinZoom = 10;
10186
}
10287

103-
// changeover 2.7 - for removal
104-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
105-
if (typeof (settings as any).aisShowTrack !== 'undefined') {
106-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
107-
settings.selections.aisShowTrack = (settings as any).aisShowTrack;
108-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
109-
delete (settings as any).aisShowTrack;
110-
}
111-
11288
if (typeof settings.toolBarButtons === 'undefined') {
11389
settings.toolBarButtons = true;
11490
}
@@ -298,6 +274,7 @@ export const DefaultConfig: IAppConfig = {
298274
center: [0, 0],
299275
rotation: 0,
300276
moveMap: false,
277+
lockMoveMap: true,
301278
northUp: true,
302279
animate: false,
303280
limitZoom: false,
@@ -424,6 +401,7 @@ export interface IAppConfig {
424401
center: Position;
425402
rotation: number;
426403
moveMap: boolean;
404+
lockMoveMap: boolean;
427405
northUp: boolean;
428406
animate: boolean;
429407
limitZoom: boolean;

src/app/modules/map/fb-map.component.html

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -533,24 +533,24 @@
533533
>
534534
</fb-xte-path>
535535
} @if(dfeat.navData.position && app.config.selections.vessel.laylines) {
536-
<fb-layline
537-
[lines]="vesselLines.laylines"
538-
[laylineStyles]="featureStyles.layline"
539-
[position]="app.data.vessels.active.position"
540-
[twd]="app.data.vessels.self.wind.twd"
541-
[mapZoom]="fbMap.zoomLevel"
542-
[zIndex]="212"
543-
>
544-
</fb-layline>
545536
<fb-target-angle
546537
[line]="vesselLines.targetAngle"
547538
[lineStyle]="featureStyles.targetAngle"
548539
[position]="app.data.vessels.active.position"
549-
[twd]="app.data.vessels.self.wind.twd"
540+
[twd]="app.data.vessels.self.wind.direction"
550541
[mapZoom]="fbMap.zoomLevel"
551542
[zIndex]="212"
552543
>
553544
</fb-target-angle>
545+
<fb-layline
546+
[lines]="vesselLines.laylines"
547+
[laylineStyles]="featureStyles.layline"
548+
[position]="app.data.vessels.active.position"
549+
[twd]="app.data.vessels.self.wind.direction"
550+
[mapZoom]="fbMap.zoomLevel"
551+
[zIndex]="212"
552+
>
553+
</fb-layline>
554554
} @if(dfeat.navData.position && app.data.anchor.raised) {
555555
<fb-bearing-line
556556
[marker]="dfeat.navData.position"

src/app/modules/map/fb-map.component.ts

Lines changed: 92 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ import {
3030
import { FreeboardOpenlayersModule } from 'src/app/modules/map/ol';
3131
import { PipesModule } from 'src/app/lib/pipes';
3232

33-
import { computeDestinationPoint, getGreatCircleBearing } from 'geolib';
33+
import {
34+
computeDestinationPoint,
35+
getGreatCircleBearing,
36+
getDistanceFromLine,
37+
getDistance,
38+
getPreciseDistance
39+
} from 'geolib';
3440
import { toLonLat } from 'ol/proj';
3541
import { Style, Stroke, Fill } from 'ol/style';
3642
import { Collection, Feature } from 'ol';
@@ -709,8 +715,10 @@ export class FBMapComponent implements OnInit, OnDestroy {
709715
}
710716

711717
public onMapPointerDrag() {
712-
this.fbMap.movingMap = false;
713-
this.exitedMovingMap.emit(true);
718+
if (!this.app.config.map.lockMoveMap) {
719+
this.fbMap.movingMap = false;
720+
this.exitedMovingMap.emit(true);
721+
}
714722
}
715723

716724
// toggle display of resource feature
@@ -1215,107 +1223,119 @@ export class FBMapComponent implements OnInit, OnDestroy {
12151223
typeof this.app.data.vessels.active.heading === 'number'
12161224
) {
12171225
const twd_deg = Convert.radiansToDegrees(
1218-
this.app.data.vessels.self.wind.twd
1226+
this.app.data.vessels.self.wind.direction
12191227
);
1228+
1229+
const twd_inv = Angle.add(twd_deg, 180);
1230+
12201231
const destUpwind =
12211232
Math.abs(
12221233
Angle.difference(this.app.data.navData.bearing.value, twd_deg)
12231234
) < 90;
1235+
12241236
const ba_deg = Convert.radiansToDegrees(
12251237
this.app.data.vessels.self.performance.beatAngle ?? Math.PI / 4
12261238
);
1227-
const destInTarget =
1228-
Math.abs(
1229-
Angle.difference(this.app.data.navData.bearing.value, twd_deg)
1230-
) < ba_deg;
1239+
1240+
const ga_deg = Convert.radiansToDegrees(
1241+
this.app.data.vessels.self.performance.gybeAngle ?? Math.PI / 6
1242+
);
1243+
1244+
const destInTarget = destUpwind
1245+
? Math.abs(
1246+
Angle.difference(this.app.data.navData.bearing.value, twd_deg)
1247+
) < ba_deg
1248+
: Math.abs(
1249+
Angle.difference(this.app.data.navData.bearing.value, twd_deg)
1250+
) > ga_deg;
1251+
12311252
const dtg =
12321253
this.app.config.units.distance === 'm'
12331254
? this.app.data.navData.dtg * 1000
12341255
: Convert.nauticalMilesToKm(this.app.data.navData.dtg * 1000);
12351256

1236-
if (destInTarget) {
1237-
const bta = Angle.add(twd_deg, 90); // tack angle = 90
1238-
1239-
const hbd_rad = Convert.degreesToRadians(
1240-
Angle.difference(twd_deg, this.app.data.navData.bearing.value)
1241-
);
1242-
const dist1 = Math.sin(hbd_rad) * dtg;
1243-
const dist2 = Math.cos(hbd_rad) * dtg;
1244-
const pt1 = computeDestinationPoint(
1245-
this.app.data.vessels.active.position,
1246-
dist1,
1247-
bta
1248-
);
1249-
const pt2 = computeDestinationPoint(
1250-
this.app.data.vessels.active.position,
1251-
dist2,
1252-
twd_deg
1253-
);
1254-
const p1a = [
1255-
this.app.data.vessels.active.position,
1256-
[pt1.longitude, pt1.latitude]
1257-
];
1258-
const p1b = [
1259-
[pt1.longitude, pt1.latitude],
1260-
this.dfeat.navData.position
1261-
];
1262-
const l1 = hbd_rad < 0 ? [p1a, p1b] : [p1b, p1a];
1263-
1264-
const p2a = [
1265-
[pt2.longitude, pt2.latitude],
1266-
this.dfeat.navData.position
1267-
];
1268-
const p2b = [
1269-
this.app.data.vessels.active.position,
1270-
[pt2.longitude, pt2.latitude]
1271-
];
1272-
const l2 = hbd_rad < 0 ? [p2a, p2b] : [p2b, p2a];
1273-
1274-
vl.laylines = {
1275-
port: hbd_rad < 0 ? l2 : l1,
1276-
starboard: hbd_rad < 0 ? l1 : l2
1277-
};
1278-
}
1279-
// target angle lines
1280-
if (destUpwind && destInTarget) {
1257+
// mark laylines
1258+
let markLines = [];
1259+
if (destUpwind) {
12811260
const bapt1 = computeDestinationPoint(
1282-
this.app.data.vessels.active.position,
1261+
this.dfeat.navData.position,
12831262
dtg,
1284-
Angle.add(twd_deg, ba_deg)
1263+
Angle.add(twd_inv, ba_deg)
12851264
);
12861265
const bapt2 = computeDestinationPoint(
1287-
this.app.data.vessels.active.position,
1266+
this.dfeat.navData.position,
12881267
dtg,
1289-
Angle.add(twd_deg, 0 - ba_deg)
1268+
Angle.add(twd_inv, 0 - ba_deg)
12901269
);
1291-
vl.targetAngle = [
1270+
1271+
markLines = [
12921272
[bapt1.longitude, bapt1.latitude],
1293-
this.app.data.vessels.active.position,
1273+
this.dfeat.navData.position,
12941274
[bapt2.longitude, bapt2.latitude]
12951275
];
1296-
} else if (
1297-
!destUpwind &&
1298-
typeof this.app.data.vessels.self.performance.gybeAngle === 'number'
1299-
) {
1300-
const ga_deg = Convert.radiansToDegrees(
1301-
this.app.data.vessels.self.performance.gybeAngle
1302-
);
1276+
} else {
13031277
const gapt1 = computeDestinationPoint(
1304-
this.app.data.vessels.active.position,
1278+
this.dfeat.navData.position,
13051279
dtg,
1306-
Angle.add(this.app.data.navData.bearing.value, ga_deg)
1280+
Angle.add(twd_deg, ga_deg)
13071281
);
13081282
const gapt2 = computeDestinationPoint(
1309-
this.app.data.vessels.active.position,
1283+
this.dfeat.navData.position,
13101284
dtg,
1311-
Angle.add(this.app.data.navData.bearing.value, 0 - ga_deg)
1285+
Angle.add(twd_deg, 0 - ga_deg)
13121286
);
1313-
vl.targetAngle = [
1287+
1288+
markLines = [
13141289
[gapt1.longitude, gapt1.latitude],
1315-
this.app.data.vessels.active.position,
1290+
this.dfeat.navData.position,
13161291
[gapt2.longitude, gapt2.latitude]
13171292
];
13181293
}
1294+
1295+
vl.targetAngle = markLines;
1296+
1297+
// vessel laylines
1298+
if (destInTarget && destUpwind) {
1299+
// Vector angles
1300+
const hbd_deg = Angle.difference(
1301+
twd_deg,
1302+
this.app.data.navData.bearing.value
1303+
);
1304+
const C_RAD = Convert.degreesToRadians(ba_deg - hbd_deg);
1305+
const B_RAD = Convert.degreesToRadians(ba_deg + hbd_deg);
1306+
const A_RAD = Math.PI - (B_RAD + C_RAD);
1307+
// Vector lengths
1308+
const b = (dtg * Math.sin(B_RAD)) / Math.sin(A_RAD);
1309+
const c = (dtg * Math.sin(C_RAD)) / Math.sin(A_RAD);
1310+
// intersection points
1311+
const ipts = computeDestinationPoint(
1312+
this.app.data.vessels.active.position,
1313+
b,
1314+
Angle.add(twd_deg, ba_deg)
1315+
);
1316+
const iptp = computeDestinationPoint(
1317+
this.app.data.vessels.active.position,
1318+
c,
1319+
Angle.add(twd_deg, 0 - ba_deg)
1320+
);
1321+
1322+
vl.laylines = {
1323+
port: [
1324+
[
1325+
[iptp.longitude, iptp.latitude],
1326+
this.app.data.vessels.active.position
1327+
],
1328+
[
1329+
[ipts.longitude, ipts.latitude],
1330+
this.app.data.vessels.active.position
1331+
]
1332+
],
1333+
starboard: [
1334+
[[ipts.longitude, ipts.latitude], markLines[1]],
1335+
[markLines[1], [iptp.longitude, iptp.latitude]]
1336+
]
1337+
};
1338+
}
13191339
}
13201340

13211341
// AWA (focused)

src/app/modules/settings/components/settings-dialog.html

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@
129129
<mat-card class="setting-card">
130130
<mat-card-content>
131131
<div class="setting-card-row" style="padding-bottom: 10px">
132+
<div class="setting-card-row-item">
133+
<mat-checkbox
134+
#lockMoveMap
135+
[(ngModel)]="facade.settings.map.lockMoveMap"
136+
(change)="onFormChange($event, lockMoveMap)"
137+
matTooltip="Do not exit follow vessel when map is panned."
138+
label="after"
139+
>
140+
Lock Follow Vessel
141+
</mat-checkbox>
142+
</div>
132143
<div class="setting-card-row-item">
133144
<mat-checkbox
134145
#muteAllSound

src/app/modules/skstream/skstream.facade.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@ export class SKStreamFacade {
360360
private processVessel(d: SKVessel) {
361361
d.cog = this.app.useMagnetic ? d.cogMagnetic : d.cogTrue;
362362
d.heading = this.app.useMagnetic ? d.headingMagnetic : d.headingTrue;
363+
d.wind.direction = this.app.useMagnetic ? d.wind.mwd : d.wind.twd;
363364
}
364365

365366
// ** process course data
1.72 KB
Loading

src/assets/help/index.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,7 @@ <h4><i class="material-icons">settings</i> Settings</h4>
17711771

17721772
<b>DISPLAY:</b><br />
17731773
This section provides choices about how information is displayed.<br />
1774-
<img src="./img/settings_display.png" style="width: 300px" alt="" />
1774+
<img src="./img/settings_display.png" style="width: 350px" alt="" />
17751775
<ul>
17761776
<li>
17771777
<b>Instrument Panel App</b>: Select from a list of installed
@@ -1801,6 +1801,10 @@ <h4><i class="material-icons">settings</i> Settings</h4>
18011801
These selected Web App can be "switched in" for display in the
18021802
<i>Instrument Panel</i>.
18031803
</li>
1804+
<li>
1805+
<b>Lock Follow Vessel</b>: Check this box to remain in "Follow
1806+
Vessel" mode when map is panned / moved.
1807+
</li>
18041808
<li>
18051809
<b>Do not Play Sounds</b>: Check this box if you do not want any
18061810
sounds played.

0 commit comments

Comments
 (0)