/** * רינדור ישויות DXF על מפת Leaflet. * כל קובץ → L.layerGroup אחד; בתוכו קבוצה לכל שכבת DXF (להדלקה/כיבוי). * טקסטים מוצגים רק מזום מסוים כדי לא להציף את המסך. */ (function (global) { "use strict"; var TEXT_MIN_ZOOM = 16; /** * @param {object} file רשומת קובץ (entities, coordSys, calibration, bbox, opacity) * @param {function} transform [x,y]→[lat,lng] * @param {boolean} darkBase רקע כהה (לוויין) — משפיע על צבעי ACI 7 * @returns {{group: L.LayerGroup, byLayer: Object, texts: Array}} * * הטקסטים מוחזרים כרשומות גולמיות ({ll, layer, html}) ולא כסמנים — * בקבצים כמו מפות כתובות יש עשרות אלפי תוויות, והאפליקציה יוצרת * אלמנטי DOM רק לאלה שנמצאות באזור התצוגה הנוכחי (עד תקרה). */ function buildLayers(file, transform, darkBase) { var byLayer = {}; var texts = []; var opacity = file.opacity !== undefined ? file.opacity : 1; var weight = file.weight || 2; function layerGroup(name) { if (!byLayer[name]) byLayer[name] = L.layerGroup(); return byLayer[name]; } file.entities.forEach(function (e) { var color = darkBase ? e.colorDark : e.color; var lg = layerGroup(e.layer); if (e.type === "poly") { var latlngs; try { latlngs = e.pts.map(transform); } catch (err) { return; } var opts = { color: color, weight: weight, opacity: opacity, interactive: false }; if (e.closed) { opts.fill = false; lg.addLayer(L.polygon(latlngs, opts)); } else { lg.addLayer(L.polyline(latlngs, opts)); } } else if (e.type === "point") { var ll; try { ll = transform(e.pt); } catch (err) { return; } lg.addLayer(L.circleMarker(ll, { radius: file.pointRadius || 3, color: color, fillColor: color, fillOpacity: opacity, opacity: opacity, weight: 1, interactive: false, })); } else if (e.type === "text") { var tl; try { tl = transform(e.pt); } catch (err) { return; } var rot = e.rotation ? " transform:rotate(" + (-e.rotation) + "deg); transform-origin:right bottom;" : ""; texts.push({ ll: tl, layer: e.layer, html: '' + escapeHtml(e.text).replace(/\n/g, "
") + "
", }); } }); var group = L.layerGroup(); Object.keys(byLayer).forEach(function (name) { group.addLayer(byLayer[name]); }); return { group: group, byLayer: byLayer, texts: texts }; } function escapeHtml(s) { return s.replace(/&/g, "&").replace(//g, ">"); } /** גבולות הקובץ ב-latlng לפי הטרנספורמציה */ function fileBounds(file, transform) { var b = file.bbox; var corners = [ [b.minX, b.minY], [b.minX, b.maxY], [b.maxX, b.minY], [b.maxX, b.maxY], ].map(transform); return L.latLngBounds(corners); } /** מוצא את קודקוד השרטוט הקרוב ביותר לנקודת מפה (לכיול) */ function nearestVertex(file, transform, latlng, map, maxPx) { var best = null, bestDist = Infinity; var target = map.latLngToLayerPoint(latlng); file.entities.forEach(function (e) { var pts = e.pts || (e.pt ? [e.pt] : []); pts.forEach(function (p) { var ll; try { ll = transform(p); } catch (err) { return; } var pp = map.latLngToLayerPoint(ll); var dx = pp.x - target.x, dy = pp.y - target.y; var d = dx * dx + dy * dy; if (d < bestDist) { bestDist = d; best = { src: p, latlng: ll }; } }); }); if (!best || Math.sqrt(bestDist) > (maxPx || 40)) return null; return best; } global.Render = { buildLayers: buildLayers, fileBounds: fileBounds, nearestVertex: nearestVertex, TEXT_MIN_ZOOM: TEXT_MIN_ZOOM, }; })(window);