55 connecting them. It properly parses the type of fence marker.
66*/
77
8- import { useEffect , useState } from "react"
8+ import { useMemo } from "react"
99
1010// Helper imports
11- import { intToCoord } from "../../helpers/dataFormatters"
11+ import { coordToInt , intToCoord } from "../../helpers/dataFormatters"
1212
1313// Styling imports
1414import "maplibre-gl/dist/maplibre-gl.css"
1515
1616// Component imports
1717
1818// Tailwind styling
19- import { circle } from "@turf/turf"
19+ import { circle , midpoint , point } from "@turf/turf"
2020import { Layer , Source } from "react-map-gl"
21- import { useSelector } from "react-redux"
21+ import { useDispatch , useSelector } from "react-redux"
2222import resolveConfig from "tailwindcss/resolveConfig"
2323import tailwindConfig from "../../../tailwind.config"
2424import { FENCE_ITEM_COMMANDS_LIST } from "../../helpers/mavlinkConstants"
2525import { selectCurrentPage } from "../../redux/slices/droneConnectionSlice"
26- import { selectActiveTab } from "../../redux/slices/missionSlice"
26+ import {
27+ insertFencePolygonVertex ,
28+ selectActiveTab ,
29+ } from "../../redux/slices/missionSlice"
2730import DrawLineCoordinates from "./drawLineCoordinates"
2831import MarkerPin from "./markerPin"
32+ import MidpointInsertButton from "./midpointInsertButton"
2933const tailwindColors = resolveConfig ( tailwindConfig ) . theme . colors
3034
3135function getFenceCommandNumber ( value ) {
@@ -46,33 +50,87 @@ const circleCommands = [
4650]
4751
4852export default function FenceItems ( { fenceItems } ) {
53+ const dispatch = useDispatch ( )
4954 const currentPage = useSelector ( selectCurrentPage )
5055 const editable =
5156 useSelector ( selectActiveTab ) === "fence" && currentPage === "missions"
5257
53- const [ fencePolygonItems , setFencePolygonItems ] = useState ( [ ] )
54- const [ fenceCircleItems , setFenceCircleItems ] = useState ( [ ] )
58+ const { fencePolygonGroups, fencePolygonItems, fenceCircleItems } =
59+ useMemo ( ( ) => {
60+ const polygonItems = [ ]
61+ const circleItems = [ ]
62+ const polygonGroups = [ ]
5563
56- useEffect ( ( ) => {
57- // Filter out fence items based on their type
58- const polygonItems = fenceItems . filter ( ( item ) =>
59- polygonCommands . includes ( item . command ) ,
60- )
61- const circleItems = fenceItems . filter ( ( item ) =>
62- circleCommands . includes ( item . command ) ,
63- )
64+ let currentGroup = [ ]
65+ let currentGroupStartIndex = null
6466
65- setFencePolygonItems ( polygonItems )
66- setFenceCircleItems ( circleItems )
67- } , [ fenceItems ] )
67+ fenceItems . forEach ( ( item , index ) => {
68+ if ( polygonCommands . includes ( item . command ) ) {
69+ const polygonItem = { ...item , fenceIndex : index }
70+ polygonItems . push ( polygonItem )
71+
72+ if ( currentGroup . length === 0 ) {
73+ currentGroupStartIndex = index
74+ }
75+
76+ currentGroup . push ( polygonItem )
77+
78+ if ( currentGroup . length === item . param1 ) {
79+ polygonGroups . push ( {
80+ items : currentGroup ,
81+ startIndex : currentGroupStartIndex ,
82+ } )
83+ currentGroup = [ ]
84+ currentGroupStartIndex = null
85+ }
86+
87+ return
88+ }
89+
90+ if ( circleCommands . includes ( item . command ) ) {
91+ circleItems . push ( { ...item , fenceIndex : index } )
92+ }
93+ } )
94+
95+ return {
96+ fencePolygonGroups : polygonGroups ,
97+ fencePolygonItems : polygonItems ,
98+ fenceCircleItems : circleItems ,
99+ }
100+ } , [ fenceItems ] )
101+
102+ const polygonEdgeInsertButtons = useMemo ( ( ) => {
103+ if ( ! editable ) return [ ]
104+
105+ return fencePolygonGroups . flatMap ( ( polygon ) => {
106+ if ( polygon . items . length < 2 ) return [ ]
107+
108+ return polygon . items . map ( ( item , index ) => {
109+ const nextItem = polygon . items [ ( index + 1 ) % polygon . items . length ]
110+ const midpointCoords = midpoint (
111+ point ( [ intToCoord ( item . y ) , intToCoord ( item . x ) ] ) ,
112+ point ( [ intToCoord ( nextItem . y ) , intToCoord ( nextItem . x ) ] ) ,
113+ ) . geometry . coordinates
114+
115+ return {
116+ afterId : item . id ,
117+ polygonStartIndex : polygon . startIndex ,
118+ polygonLength : polygon . items . length ,
119+ lat : midpointCoords [ 1 ] ,
120+ lon : midpointCoords [ 0 ] ,
121+ tooltipText : `Insert vertex between ${ item . z + 1 } and ${ nextItem . z + 1 } ` ,
122+ }
123+ } )
124+ } )
125+ } , [ editable , fencePolygonGroups ] )
68126
69127 return (
70128 < >
71129 { /* Show mission geo-fence MARKERS */ }
72130 { fencePolygonItems . map ( ( item , index ) => {
73131 return (
74132 < MarkerPin
75- key = { index }
133+ key = { item . id || index }
76134 id = { item . id }
77135 lat = { intToCoord ( item . x ) }
78136 lon = { intToCoord ( item . y ) }
@@ -82,25 +140,31 @@ export default function FenceItems({ fenceItems }) {
82140 )
83141 } ) }
84142
143+ { polygonEdgeInsertButtons . map ( ( button ) => (
144+ < MidpointInsertButton
145+ key = { `${ button . afterId } :${ button . polygonStartIndex } ` }
146+ lat = { button . lat }
147+ lon = { button . lon }
148+ colour = { tailwindColors . blue [ 400 ] }
149+ tooltipText = { button . tooltipText }
150+ onClick = { ( ) => {
151+ dispatch (
152+ insertFencePolygonVertex ( {
153+ afterId : button . afterId ,
154+ polygonStartIndex : button . polygonStartIndex ,
155+ polygonLength : button . polygonLength ,
156+ x : coordToInt ( button . lat ) ,
157+ y : coordToInt ( button . lon ) ,
158+ } ) ,
159+ )
160+ } }
161+ />
162+ ) ) }
163+
85164 { /* Group fencePolygonItems into separate polygons */ }
86165 { ( ( ) => {
87- const polygons = [ ]
88- let currentPolygon = [ ]
89- let currentPoints = 0
90-
91- fencePolygonItems . forEach ( ( item ) => {
92- currentPolygon . push ( item )
93- currentPoints ++
94-
95- if ( currentPoints === item . param1 ) {
96- polygons . push ( currentPolygon )
97- currentPolygon = [ ]
98- currentPoints = 0
99- }
100- } )
101-
102- return polygons . map ( ( polygon , index ) => {
103- const lastPolygonItem = polygon [ polygon . length - 1 ]
166+ return fencePolygonGroups . map ( ( polygon , index ) => {
167+ const lastPolygonItem = polygon . items [ polygon . items . length - 1 ]
104168
105169 const color =
106170 lastPolygonItem . command === 5002
@@ -111,11 +175,14 @@ export default function FenceItems({ fenceItems }) {
111175 < DrawLineCoordinates
112176 key = { index }
113177 coordinates = { [
114- ...polygon . map ( ( item ) => [
178+ ...polygon . items . map ( ( item ) => [
115179 intToCoord ( item . y ) ,
116180 intToCoord ( item . x ) ,
117181 ] ) ,
118- [ intToCoord ( polygon [ 0 ] . y ) , intToCoord ( polygon [ 0 ] . x ) ] ,
182+ [
183+ intToCoord ( polygon . items [ 0 ] . y ) ,
184+ intToCoord ( polygon . items [ 0 ] . x ) ,
185+ ] ,
119186 ] }
120187 colour = { color }
121188 lineProps = { { "line-width" : 2 , "line-dasharray" : [ 4 , 6 ] } }
0 commit comments