fix(markarbejde): markens omrids fra getDensityMapPolygon (FS25 har ingen polygonPoints) — flere prøvepunkter, markør-afstand til kanten; F108 majs sås som bar jord og F<nr>-markører 'manglede' på store marker (v1.28.6.0)
This commit is contained in:
@@ -151,13 +151,63 @@ local function isOnField(x, z)
|
||||
return FSDensityMapUtil.getFieldDataAtWorldPosition(x, y, z) and true or false
|
||||
end
|
||||
|
||||
local function findMarker(adEnv, fieldId, x, z)
|
||||
ADFields.SAMPLE_DIRECTIONS = 16
|
||||
|
||||
-- Markens omrids som {{x, z}, ...}. FS25: field:getDensityMapPolygon():getVerticesList() (flad liste
|
||||
-- x1, z1, x2, z2 ... — som Courseplay); ældre: polygonPoints (noder). Tom liste hvis intet findes.
|
||||
function ADFields.readPolygon(field)
|
||||
local verts = {}
|
||||
local okList, list = pcall(function()
|
||||
return field.getDensityMapPolygon ~= nil and field:getDensityMapPolygon():getVerticesList() or nil
|
||||
end)
|
||||
if okList and type(list) == "table" and #list >= 6 then
|
||||
for index = 1, #list - 1, 2 do
|
||||
table.insert(verts, {x = list[index], z = list[index + 1]})
|
||||
end
|
||||
return verts
|
||||
end
|
||||
for _, node in ipairs(field.polygonPoints or {}) do
|
||||
if type(node) == "number" then
|
||||
local x, _, z = getWorldTranslation(node)
|
||||
table.insert(verts, {x = x, z = z})
|
||||
end
|
||||
end
|
||||
return verts
|
||||
end
|
||||
|
||||
-- Hjørnernes gennemsnit (nil uden hjørner).
|
||||
function ADFields.polygonCenter(verts)
|
||||
if verts == nil or #verts == 0 then return nil end
|
||||
local cx, cz = 0, 0
|
||||
for _, v in ipairs(verts) do cx, cz = cx + v.x, cz + v.z end
|
||||
return cx / #verts, cz / #verts
|
||||
end
|
||||
|
||||
-- Afstand fra (x, z) til omridsets nærmeste kant; nil uden omrids.
|
||||
function ADFields.distanceToPolygon(verts, x, z)
|
||||
if verts == nil or #verts == 0 then return nil end
|
||||
local best = math.huge
|
||||
for index = 1, #verts do
|
||||
local a, b = verts[index], verts[index % #verts + 1]
|
||||
local dx, dz = b.x - a.x, b.z - a.z
|
||||
local len2 = dx * dx + dz * dz
|
||||
local t = len2 > 0 and math.max(0, math.min(1, ((x - a.x) * dx + (z - a.z) * dz) / len2)) or 0
|
||||
local d = math.sqrt((a.x + dx * t - x) ^ 2 + (a.z + dz * t - z) ^ 2)
|
||||
if d < best then best = d end
|
||||
end
|
||||
return best
|
||||
end
|
||||
|
||||
-- Markøren "F<nr>" nærmest marken: afstand til omridset (markører står ved kanten; midten kan
|
||||
-- ligge 900 m væk på store kort), ellers til midten.
|
||||
local function findMarker(adEnv, fieldId, x, z, verts)
|
||||
local best, bestDistance = nil, math.huge
|
||||
for _, marker in pairs(adEnv.ADGraphManager:getMapMarkers()) do
|
||||
if ADFields.parseMarkerName(marker.name) == fieldId then
|
||||
local wayPoint = adEnv.ADGraphManager:getWayPointById(marker.id)
|
||||
if wayPoint ~= nil then
|
||||
local distance = math.sqrt((wayPoint.x - x) ^ 2 + (wayPoint.z - z) ^ 2)
|
||||
local distance = ADFields.distanceToPolygon(verts, wayPoint.x, wayPoint.z)
|
||||
or math.sqrt((wayPoint.x - x) ^ 2 + (wayPoint.z - z) ^ 2)
|
||||
if distance < bestDistance then best, bestDistance = marker, distance end
|
||||
end
|
||||
end
|
||||
@@ -199,24 +249,19 @@ local function newScan(adEnv, entry)
|
||||
scan.info = info
|
||||
-- 1) polygon og kandidatpunkter (centroid + halvvejs mod op til 8 hjørner)
|
||||
push(scan, function()
|
||||
local verts = {}
|
||||
for _, node in ipairs(field.polygonPoints or {}) do
|
||||
if type(node) == "number" then
|
||||
local x, _, z = getWorldTranslation(node)
|
||||
table.insert(verts, {x = x, z = z})
|
||||
end
|
||||
end
|
||||
local verts = ADFields.readPolygon(field)
|
||||
info.verts = verts
|
||||
local cx, cz = field.posX, field.posZ
|
||||
if (cx == nil or cz == nil) and #verts > 0 then
|
||||
cx, cz = 0, 0
|
||||
for _, v in ipairs(verts) do cx, cz = cx + v.x, cz + v.z end
|
||||
cx, cz = cx / #verts, cz / #verts
|
||||
end
|
||||
local cx, cz = ADFields.polygonCenter(verts)
|
||||
if cx == nil then cx, cz = field.posX, field.posZ end
|
||||
info.x, info.z = cx, cz
|
||||
if cx == nil then return end
|
||||
-- midten, markskiltet og halvvejs mod op til SAMPLE_DIRECTIONS hjørner: store marker (Dakota
|
||||
-- 16x: 1,7 km) har striber uden afgrøde, så ét punkt kan ramme forkert
|
||||
local candidates = {{x = cx, z = cz}}
|
||||
local step = math.max(1, math.floor(#verts / 8))
|
||||
if field.posX ~= nil and field.posZ ~= nil and (field.posX - cx) ^ 2 + (field.posZ - cz) ^ 2 > 1 then
|
||||
table.insert(candidates, {x = field.posX, z = field.posZ})
|
||||
end
|
||||
local step = math.max(1, math.floor(#verts / ADFields.SAMPLE_DIRECTIONS))
|
||||
for index = 1, #verts, step do
|
||||
table.insert(candidates, {x = (cx + verts[index].x) / 2, z = (cz + verts[index].z) / 2})
|
||||
end
|
||||
@@ -318,7 +363,7 @@ local function finishScan(adEnv, scan)
|
||||
if previous ~= nil and previous.markerCheckedAt ~= nil and ADFields.now - previous.markerCheckedAt < ADFields.MARKER_REFRESH_MS then
|
||||
info.markerId, info.markerName, info.markerDistance, info.markerCheckedAt = previous.markerId, previous.markerName, previous.markerDistance, previous.markerCheckedAt
|
||||
elseif info.x ~= nil then
|
||||
local marker, distance = findMarker(adEnv, info.id, info.x, info.z)
|
||||
local marker, distance = findMarker(adEnv, info.id, info.x, info.z, info.verts)
|
||||
info.markerId = marker ~= nil and marker.id or nil
|
||||
info.markerName = marker ~= nil and marker.name or nil
|
||||
info.markerDistance = distance
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<modDesc descVersion="107">
|
||||
<author>masterdraco</author>
|
||||
<version>1.28.5.0</version>
|
||||
<version>1.28.6.0</version>
|
||||
<title>
|
||||
<en>AD Smart Pickup</en>
|
||||
</title>
|
||||
|
||||
Reference in New Issue
Block a user