Commit a695183b authored by sxl's avatar sxl 💬

fix:水位线坐标调整

parent 61b11b3a
......@@ -1079,7 +1079,7 @@ export default {
sx: holeX,
sy: ladderSY,
ex: holeX,
ey: holeEndY,
ey: holeEndY + device.holeBaseElevation, // 控制穿孔线的长度
width: lineW,
color: 'grey'
})
......@@ -1088,15 +1088,16 @@ export default {
var deviceSY = deviceEY - deviceH
this.drawLiner({
sx: holeX,
sy: deviceSY,
sy: deviceSY + device.holeBaseElevation,
ex: holeX,
ey: deviceEY,
ey: deviceEY + device.holeBaseElevation,
width: deviceW,
color: '#3403CB'
})
// 水位值的x,y坐标
this.options.deviceCoords.push({
x: holeX,
y: deviceLY,
y: deviceLY + device.holeBaseElevation,
stepY: ladderSY
})
var valFont = 11
......@@ -1105,7 +1106,7 @@ export default {
this.drawText({
x: holeX,
y: valueSY,
y: valueSY + device.holeBaseElevation,
size: valFont,
text: text,
color: 'white',
......@@ -1113,50 +1114,44 @@ export default {
})
}
// 连接所有水位值,只在首尾延长
// 连接所有水位值,使用曲线连接,只在首尾延长
var deviceCoords = this.options.deviceCoords || []
// 新增:如果水位值坐标在边坡边界外面,则不参与连线(按点级别过滤)
if (this.options.enableBoundaryLimit && this.bianpoLinePoinArr && this.bianpoLinePoinArr.length > 1) {
deviceCoords = deviceCoords.filter(function(pt) {
return !this.checkIfPointOutsideSlope(pt)
}.bind(this))
}
// 按X坐标从左到右排序(因为设备X坐标是 endX - device.x 计算的,可能需要排序)
deviceCoords.sort(function(a, b) {
return a.x - b.x
})
console.log('排序后的设备坐标:', deviceCoords.map(d => ({ x: d.x, y: d.y })))
// 新增:若过滤后不足2个点,则不绘制连接线
if (deviceCoords.length < 2) {
return
}
if (deviceCoords.length >= 2) {
// 计算延伸距离(可以根据需要调整)
var extensionLength = 30 * this.dpr // 延伸30像素
// 连接所有相邻的水位点
for (var i = 0; i < deviceCoords.length - 1; i++) {
var currentDevice = deviceCoords[i]
var nextDevice = deviceCoords[i + 1]
// 只绘制设备之间的连线,不延伸
this.drawLiner({
sx: currentDevice.x,
sy: currentDevice.y,
ex: nextDevice.x,
ey: nextDevice.y,
width: 2,
color: 'blue'
})
}
// 准备曲线点数组
var curvePoints = []
var needCurveConnection = false // 标记是否需要曲线连接
// 只在第一个和最后一个水位值点处理延伸线
// 处理左侧延伸点
var firstDevice = deviceCoords[0]
var lastDevice = deviceCoords[deviceCoords.length - 1]
var secondDevice = deviceCoords[1]
var secondLastDevice = deviceCoords[deviceCoords.length - 2]
var chartMinX = this.options.initX
var chartMaxX = this.options.endX
var chartMinY = this.options.initY
var chartMaxY = this.options.endY
var shrinkDistance = 10 * this.dpr
var shrinkDistance = 15 * this.dpr // 安全距离 15px
// 处理第一个点的左侧延伸线
// 判断:如果第一个和第二个X坐标相同,则不绘制延伸线
// 计算左侧延伸点
if (firstDevice && secondDevice && Math.abs(firstDevice.x - secondDevice.x) > 1) {
var dx1 = secondDevice.x - firstDevice.x
var dy1 = secondDevice.y - firstDevice.y
......@@ -1171,27 +1166,29 @@ export default {
startX = Math.max(chartMinX, Math.min(chartMaxX, startX))
startY = Math.max(chartMinY, Math.min(chartMaxY, startY))
// 如果启用边界限制,找到延伸线与边坡线的交点
// 如果启用边界限制,找到延伸线与边坡线的交点(按y最小选择)
if (this.options.enableBoundaryLimit && this.bianpoLinePoinArr.length > 0) {
var leftIntersections = []
for (var j = 0; j < this.bianpoLinePoinArr.length - 1; j++) {
var slopePoint1 = this.bianpoLinePoinArr[j]
var slopePoint2 = this.bianpoLinePoinArr[j + 1]
var leftIntersection = this.getLineIntersection(
for (var m = 0; m < this.bianpoLinePoinArr.length - 1; m++) {
var slopePoint1 = this.bianpoLinePoinArr[m]
var slopePoint2 = this.bianpoLinePoinArr[m + 1]
var interL = this.getLineIntersection(
firstDevice.x, firstDevice.y, startX, startY,
slopePoint1.x, slopePoint1.y, slopePoint2.x, slopePoint2.y
)
if (leftIntersection) {
leftIntersections.push(leftIntersection)
if (interL && interL.t >= 0 && interL.t <= 1 && interL.u >= 0 && interL.u <= 1) {
leftIntersections.push(interL)
}
}
if (leftIntersections.length > 0) {
var closestLeft = leftIntersections.reduce((closest, current) => {
var closestDist = Math.abs(closest.x - firstDevice.x)
var currentDist = Math.abs(current.x - firstDevice.x)
return currentDist < closestDist ? current : closest
})
// 选择y最小(更靠上)的交点,若并列取t最小
var closestLeft = leftIntersections.reduce(function(best, cur) {
if (!best) return cur
if (cur.y < best.y - 1e-6) return cur
if (Math.abs(cur.y - best.y) <= 1e-6) return (cur.t < best.t ? cur : best)
return best
}, null)
var leftDx = firstDevice.x - closestLeft.x
var leftDy = firstDevice.y - closestLeft.y
var leftLength = Math.sqrt(leftDx * leftDx + leftDy * leftDy)
......@@ -1200,6 +1197,7 @@ export default {
var leftUnitY = leftDy / leftLength
startX = closestLeft.x + leftUnitX * shrinkDistance
startY = closestLeft.y + leftUnitY * shrinkDistance
needCurveConnection = true // 标记需要曲线连接
} else {
startX = closestLeft.x
startY = closestLeft.y
......@@ -1207,19 +1205,17 @@ export default {
}
}
// 绘制第一个点的左侧延伸线
this.drawLiner({
sx: startX,
sy: startY,
ex: firstDevice.x,
ey: firstDevice.y,
width: 2,
color: 'blue'
})
curvePoints.push({ x: startX, y: startY })
}
// 处理最后一个点的右侧延伸线
// 判断:如果最后一个和倍数第二个X坐标相同,则不绘制延伸线
// 添加所有设备点
curvePoints.push(...deviceCoords)
// 处理右侧延伸点
var lastDevice = deviceCoords[deviceCoords.length - 1]
var secondLastDevice = deviceCoords[deviceCoords.length - 2]
// 计算右侧延伸点
if (lastDevice && secondLastDevice && Math.abs(lastDevice.x - secondLastDevice.x) > 1) {
var dx2 = lastDevice.x - secondLastDevice.x
var dy2 = lastDevice.y - secondLastDevice.y
......@@ -1227,58 +1223,114 @@ export default {
var unitX2 = dx2 / length2
var unitY2 = dy2 / length2
var endX = lastDevice.x + unitX2 * extensionLength
var endY = lastDevice.y + unitY2 * extensionLength
var rightEndX = lastDevice.x + unitX2 * extensionLength
var rightEndY = lastDevice.y + unitY2 * extensionLength
// 限制终点坐标
endX = Math.max(chartMinX, Math.min(chartMaxX, endX))
endY = Math.max(chartMinY, Math.min(chartMaxY, endY))
rightEndX = Math.max(chartMinX, Math.min(chartMaxX, rightEndX))
rightEndY = Math.max(chartMinY, Math.min(chartMaxY, rightEndY))
// 如果启用边界限制,找到延伸线与边坡线的交点
// 如果启用边界限制,找到延伸线与边坡线的交点(按y最小选择)
if (this.options.enableBoundaryLimit && this.bianpoLinePoinArr.length > 0) {
var rightIntersections = []
for (var j = 0; j < this.bianpoLinePoinArr.length - 1; j++) {
var slopePoint1 = this.bianpoLinePoinArr[j]
var slopePoint2 = this.bianpoLinePoinArr[j + 1]
var rightIntersection = this.getLineIntersection(
lastDevice.x, lastDevice.y, endX, endY,
for (var n = 0; n < this.bianpoLinePoinArr.length - 1; n++) {
var slopePoint1 = this.bianpoLinePoinArr[n]
var slopePoint2 = this.bianpoLinePoinArr[n + 1]
var interR = this.getLineIntersection(
lastDevice.x, lastDevice.y, rightEndX, rightEndY,
slopePoint1.x, slopePoint1.y, slopePoint2.x, slopePoint2.y
)
if (rightIntersection) {
rightIntersections.push(rightIntersection)
if (interR && interR.t >= 0 && interR.t <= 1 && interR.u >= 0 && interR.u <= 1) {
rightIntersections.push(interR)
}
}
if (rightIntersections.length > 0) {
var closestRight = rightIntersections.reduce((closest, current) => {
var closestDist = Math.abs(closest.x - lastDevice.x)
var currentDist = Math.abs(current.x - lastDevice.x)
return currentDist < closestDist ? current : closest
})
var closestRight = rightIntersections.reduce(function(best, cur) {
if (!best) return cur
if (cur.y < best.y - 1e-6) return cur
if (Math.abs(cur.y - best.y) <= 1e-6) return (cur.t < best.t ? cur : best)
return best
}, null)
var rightDx = lastDevice.x - closestRight.x
var rightDy = lastDevice.y - closestRight.y
var rightLength = Math.sqrt(rightDx * rightDx + rightDy * rightDy)
if (rightLength > 0) {
var rightUnitX = rightDx / rightLength
var rightUnitY = rightDy / rightLength
endX = closestRight.x + rightUnitX * shrinkDistance
endY = closestRight.y + rightUnitY * shrinkDistance
rightEndX = closestRight.x + rightUnitX * shrinkDistance
rightEndY = closestRight.y + rightUnitY * shrinkDistance
needCurveConnection = true // 标记需要曲线连接
} else {
endX = closestRight.x
endY = closestRight.y
rightEndX = closestRight.x
rightEndY = closestRight.y
}
}
}
// 绘制最后一个点的右侧延伸线
this.drawLiner({
sx: lastDevice.x,
sy: lastDevice.y,
ex: endX,
ey: endY,
width: 2,
color: 'blue'
})
curvePoints.push({ x: rightEndX, y: rightEndY })
}
// 两点之閴的直线是否穿过边坡,穿过则用曲线,其余用直线;两端延长线用直线
if (curvePoints.length >= 2) {
var ctx = this.ctx
ctx.lineWidth = 2
ctx.strokeStyle = 'blue'
ctx.beginPath()
ctx.moveTo(curvePoints[0].x, curvePoints[0].y)
var lastCtrl = null
for (var k = 1; k < curvePoints.length; k++) {
var pt1 = curvePoints[k - 1]
var pt2 = curvePoints[k]
// 判断是否是两端的延长线
var isEdgeExtension = (k === 1) || (k === curvePoints.length - 1)
if (isEdgeExtension && k === curvePoints.length - 1 && k >= 2) {
// 末段延伸:依据上一段切线自然延申(非近直线)
var prev = curvePoints[k - 2]
var tvx = pt1.x - prev.x; var tvy = pt1.y - prev.y
var tlen = Math.sqrt(tvx * tvx + tvy * tvy) || 1
tvx /= tlen; tvy /= tlen
var segLenR = Math.hypot(pt2.x - pt1.x, pt2.y - pt1.y)
var dR = Math.min(28 * this.dpr, segLenR * 0.6)
var cp2 = { x: pt1.x + tvx * dR, y: pt1.y + tvy * dR }
if (this.doesQuadraticCurveCrossBoundary(pt1, cp2, pt2)) {
var safeCp = this.getControlPointForCurve(pt1, pt2)
ctx.quadraticCurveTo(safeCp.x, safeCp.y, pt2.x, pt2.y)
} else {
ctx.quadraticCurveTo(cp2.x, cp2.y, pt2.x, pt2.y)
}
} else if (isEdgeExtension && k === 1 && curvePoints.length >= 3) {
// 首段延伸:在第一个设备点保持切线连续
var next = curvePoints[2] || pt2
var dirx = next.x - pt2.x; var diry = next.y - pt2.y
var dirLen = Math.sqrt(dirx * dirx + diry * diry) || 1
dirx /= dirLen; diry /= dirLen
var segLenL = Math.hypot(pt2.x - pt1.x, pt2.y - pt1.y)
var dL = Math.min(28 * this.dpr, segLenL * 0.6)
var cpL = { x: pt2.x - dirx * dL, y: pt2.y - diry * dL }
if (this.doesQuadraticCurveCrossBoundary(pt1, cpL, pt2)) {
var safeCpL = this.getControlPointForCurve(pt1, pt2)
ctx.quadraticCurveTo(safeCpL.x, safeCpL.y, pt2.x, pt2.y)
} else {
ctx.quadraticCurveTo(cpL.x, cpL.y, pt2.x, pt2.y)
}
} else {
// 其他段:原直/曲线判断
var lineSegmentCrosses = this.isLineSegmentCrossesBoundary(pt1, pt2)
if (lineSegmentCrosses) {
var controlPt = this.getControlPointForCurve(pt1, pt2)
ctx.quadraticCurveTo(controlPt.x, controlPt.y, pt2.x, pt2.y)
} else {
ctx.lineTo(pt2.x, pt2.y)
}
}
}
ctx.stroke()
}
}
},
......@@ -1551,7 +1603,8 @@ export default {
holeDepth: item.jrx_trepanning,
value: item.depth,
depth: item.jrx_burial,
waterValue: item.stage
waterValue: item.stage,
holeBaseElevation: item.holeBaseElevation
})
}
return arr
......@@ -1599,25 +1652,104 @@ export default {
ctx.strokeStyle = o.color
ctx.stroke()
},
// 计算两条线段的交点
getLineIntersection: function(x1, y1, x2, y2, x3, y3, x4, y4) {
const denom = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
if (Math.abs(denom) < 1e-10) {
return null // 平行线,无交点
// 新增:绘制曲线方法
drawCurve: function(points, width, color) {
if (!points || points.length < 2) return
var ctx = this.ctx
ctx.beginPath()
ctx.lineWidth = width || 2
ctx.strokeStyle = color || 'blue'
// 如果只有两个点,绘制简单的曲线
if (points.length === 2) {
ctx.moveTo(points[0].x, points[0].y)
// 计算控制点
var cp1x = points[0].x + (points[1].x - points[0].x) / 3
var cp1y = points[0].y
var cp2x = points[0].x + 2 * (points[1].x - points[0].x) / 3
var cp2y = points[1].y
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, points[1].x, points[1].y)
} else if (points.length >= 3) {
// 多个点,使用平滑的贝塞尔曲线连接
ctx.moveTo(points[0].x, points[0].y)
for (var i = 1; i < points.length; i++) {
var prevPoint = points[i - 1]
var currPoint = points[i]
var nextPoint = i < points.length - 1 ? points[i + 1] : null
if (nextPoint) {
// 计算当前点的控制点
var controlX = currPoint.x
var controlY = currPoint.y
// 使用二阶贝塞尔曲线绘制到中点
var midX = (currPoint.x + nextPoint.x) / 2
var midY = (currPoint.y + nextPoint.y) / 2
ctx.quadraticCurveTo(controlX, controlY, midX, midY)
} else {
// 最后一个点,直接连接
var prevPrevPoint = i > 1 ? points[i - 2] : prevPoint
var cp1x = prevPoint.x + (currPoint.x - prevPrevPoint.x) / 4
var cp1y = prevPoint.y + (currPoint.y - prevPrevPoint.y) / 4
ctx.quadraticCurveTo(cp1x, cp1y, currPoint.x, currPoint.y)
}
}
}
const t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / denom
const u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / denom
ctx.stroke()
},
// 计算两条线段的交点(数值稳定,返回x,y并附带t/u,含共线重叠处理)
getLineIntersection: function(x1, y1, x2, y2, x3, y3, x4, y4) {
const eps = 1e-9
const dx1 = x2 - x1; const dy1 = y2 - y1
const dx2 = x4 - x3; const dy2 = y4 - y3
const denom = dx1 * dy2 - dy1 * dx2
// 平行或共线
if (Math.abs(denom) < eps) {
// 是否共线:向量(x3-x1,y3-y1)与dx1,dy1的叉积≈0
const cross = (x3 - x1) * dy1 - (y3 - y1) * dx1
if (Math.abs(cross) > eps) return null
// 共线:计算重叠区间,并取重叠端点中y最小的一个
const len1sq = dx1 * dx1 + dy1 * dy1
if (len1sq < eps) return null // 退化为点
const t3 = ((x3 - x1) * dx1 + (y3 - y1) * dy1) / len1sq
const t4 = ((x4 - x1) * dx1 + (y4 - y1) * dy1) / len1sq
const tmin = Math.max(0, Math.min(t3, t4))
const tmax = Math.min(1, Math.max(t3, t4))
if (tmax + eps < tmin) return null // 无重叠
// 两个候选端点
const Ax = x1 + tmin * dx1; const Ay = y1 + tmin * dy1
const Bx = x1 + tmax * dx1; const By = y1 + tmax * dy1
let t = tmin; let ix = Ax; let iy = Ay
if (By < Ay - eps || (Math.abs(By - Ay) <= eps && tmax < tmin)) {
t = tmax; ix = Bx; iy = By
}
// 检查交点是否在两条线段上
if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
return {
x: x1 + t * (x2 - x1),
y: y1 + t * (y2 - y1)
// 对应第二段的u
const len2sq = dx2 * dx2 + dy2 * dy2
let u = 0
if (len2sq > eps) {
u = ((ix - x3) * dx2 + (iy - y3) * dy2) / len2sq
}
return { x: ix, y: iy, t, u, colinear: true }
}
return null // 无交点
// 一般情况
const t = ((x3 - x1) * dy2 - (y3 - y1) * dx2) / denom
const u = ((x3 - x1) * dy1 - (y3 - y1) * dx1) / denom
if (t >= -eps && t <= 1 + eps && u >= -eps && u <= 1 + eps) {
const ix = x1 + t * dx1
const iy = y1 + t * dy1
return { x: ix, y: iy, t, u, colinear: false }
}
return null
},
drawText: function(o) {
var ctx = this.ctx
......@@ -1738,13 +1870,17 @@ export default {
},
// 新增:检查水位线是否在边坡线上方或外部
checkIfWaterLineAboveSlope: function(currentDevice, nextDevice) {
// 检查水位线的起点和终点是否在边坡线范围内
var slopeStartX = this.bianpoLinePoinArr[0].x
var slopeEndX = this.bianpoLinePoinArr[this.bianpoLinePoinArr.length - 1].x
// 计算边坡X范围(取最小/最大,避免采样顺序影响)
var minX = Infinity; var maxX = -Infinity
for (var i = 0; i < this.bianpoLinePoinArr.length; i++) {
var px = this.bianpoLinePoinArr[i].x
if (px < minX) minX = px
if (px > maxX) maxX = px
}
// 如果水位线的任一端点超出边坡线的X范围,认为在边坡外部
if (currentDevice.x < slopeStartX || currentDevice.x > slopeEndX ||
nextDevice.x < slopeStartX || nextDevice.x > slopeEndX) {
if (currentDevice.x < minX || currentDevice.x > maxX ||
nextDevice.x < minX || nextDevice.x > maxX) {
console.log('水位线超出边坡X范围')
return true
}
......@@ -1793,13 +1929,230 @@ export default {
}
return null
},
// 修正:检查点是否在边坡外部(仅当超出边坡X范围,或在边坡线之上/图表底部之外时判为外部)
checkIfPointOutsideSlope: function(point) {
if (!this.bianpoLinePoinArr || this.bianpoLinePoinArr.length < 2) {
return false // 无边坡数据时,视为不在外部,避免误删
}
// 计算边坡X范围(取最小/最大,避免采样顺序影响)
var minX = Infinity; var maxX = -Infinity
for (var i = 0; i < this.bianpoLinePoinArr.length; i++) {
var px = this.bianpoLinePoinArr[i].x
if (px < minX) minX = px
if (px > maxX) maxX = px
}
var eps = 1e-6
// X超出边坡范围:外部
if (point.x < minX - eps || point.x > maxX + eps) {
return true
}
// 取得该X处的边坡线Y(边坡上缘)
var slopeYAtX = this.getSlopeYAtX(point.x)
if (slopeYAtX === null) {
return true
}
// 图表底部Y(允许在边坡线与底部之间为“内部”)
var bottomY = this.options && this.options.endY != null ? this.options.endY : Number.POSITIVE_INFINITY
// 在边坡线上方(更小的Y):外部;低于图表底部:外部
if (point.y < slopeYAtX - eps || point.y > bottomY + eps) {
return true
}
// 其余均视为在边坡内部
return false
},
// 新增:处理超过边坡的点,返回可见点和超过边坡的点
processPointsBeyondSlope: function(points) {
if (!points || points.length === 0) {
return { visiblePoints: [], beyondPoints: [] }
}
var visiblePoints = []
var beyondPoints = []
var currentSegment = []
var inBeyondSegment = false
for (var i = 0; i < points.length; i++) {
var point = points[i]
var isOutside = this.checkIfPointOutsideSlope(point)
if (!isOutside) {
// 点在边坡内
if (inBeyondSegment) {
// 刚从超过边坡的区域回到边坡内,需要处理交点
if (currentSegment.length > 0) {
// 找到与边坡线的交点
var intersection = this.findIntersectionWithSlope(currentSegment[currentSegment.length - 1], point)
if (intersection) {
// 将交点添加到两个段中
currentSegment.push(intersection)
beyondPoints.push(...currentSegment)
visiblePoints.push(intersection)
currentSegment = []
}
}
inBeyondSegment = false
}
visiblePoints.push(point)
} else {
// 点在边坡外
if (!inBeyondSegment) {
// 刚从边坡内进入超过边坡的区域,需要处理交点
if (visiblePoints.length > 0) {
// 找到与边坡线的交点
var intersection = this.findIntersectionWithSlope(visiblePoints[visiblePoints.length - 1], point)
if (intersection) {
// 将交点添加到两个段中
visiblePoints.push(intersection)
currentSegment.push(intersection)
}
}
inBeyondSegment = true
}
currentSegment.push(point)
}
}
// 处理最后一个段
if (inBeyondSegment && currentSegment.length > 0) {
beyondPoints.push(...currentSegment)
}
return { visiblePoints: visiblePoints, beyondPoints: beyondPoints }
},
// 新增:找到线段与边坡线的交点(取所有交点中y最小者,tie-break用t最小),返回segIndex
findIntersectionWithSlope: function(point1, point2) {
if (!this.bianpoLinePoinArr || this.bianpoLinePoinArr.length < 2) {
return null
}
var best = null
var bestY = Infinity
var eps = 1e-6
// 遍历边坡线的每个线段,收集交点
for (var i = 0; i < this.bianpoLinePoinArr.length - 1; i++) {
var slopePoint1 = this.bianpoLinePoinArr[i]
var slopePoint2 = this.bianpoLinePoinArr[i + 1]
var inter = this.getLineIntersection(
point1.x, point1.y, point2.x, point2.y,
slopePoint1.x, slopePoint1.y, slopePoint2.x, slopePoint2.y
)
if (inter && inter.t >= 0 && inter.t <= 1 && inter.u >= 0 && inter.u <= 1) {
if (inter.y < bestY - eps || (Math.abs(inter.y - bestY) <= eps && (!best || inter.t < best.t))) {
bestY = inter.y
inter.segIndex = i
best = inter
}
}
}
return best
},
// 新增:判断两点的直线连接是否会穿过边坡(优先精确判断,采样兜底)
isLineSegmentCrossesBoundary: function(point1, point2) {
if (!this.bianpoLinePoinArr || this.bianpoLinePoinArr.length < 2) {
return false // 没有边界数据,默认不穿过
}
// 1) 精确判断与任何边坡线段是否相交
var eps = 1e-6
for (var i = 0; i < this.bianpoLinePoinArr.length - 1; i++) {
var s1 = this.bianpoLinePoinArr[i]
var s2 = this.bianpoLinePoinArr[i + 1]
var inter = this.getLineIntersection(
point1.x, point1.y, point2.x, point2.y,
s1.x, s1.y, s2.x, s2.y
)
if (inter && inter.t >= -eps && inter.t <= 1 + eps && inter.u >= -eps && inter.u <= 1 + eps) {
return true
}
}
// 2) 采样兜底(处理数值贴边/共线等情况)
var sampleCount = 50
for (var s = 0; s <= sampleCount; s++) {
var t = s / sampleCount
var sampleX = point1.x + t * (point2.x - point1.x)
var sampleY = point1.y + t * (point2.y - point1.y)
var slopeYAtX = this.getSlopeYAtX(sampleX)
if (slopeYAtX !== null && sampleY > slopeYAtX) {
return true
}
}
return false
},
// 新增:检测二阶贝塞尔曲线是否与边坡有交叉(按曲线段折线化后与边坡线段做精确相交判断)
doesQuadraticCurveCrossBoundary: function(p0, cp, p1) {
if (!this.bianpoLinePoinArr || this.bianpoLinePoinArr.length < 2) return false
var samples = 64 // 折线化采样点数(>=3)
var pts = []
for (var s = 0; s <= samples; s++) {
var t = s / samples
var omt = 1 - t
pts.push({
x: omt * omt * p0.x + 2 * omt * t * cp.x + t * t * p1.x,
y: omt * omt * p0.y + 2 * omt * t * cp.y + t * t * p1.y
})
}
var eps = 1e-6
// 与每个小折线段逐段精确相交检测(两点之间的交叉点判断)
for (var i = 1; i < pts.length; i++) {
var q0 = pts[i - 1]
var q1 = pts[i]
for (var j = 0; j < this.bianpoLinePoinArr.length - 1; j++) {
var s0 = this.bianpoLinePoinArr[j]
var s1 = this.bianpoLinePoinArr[j + 1]
var inter = this.getLineIntersection(q0.x, q0.y, q1.x, q1.y, s0.x, s0.y, s1.x, s1.y)
if (inter) {
// 仅判定发生在两个折线段内的交点(排除端点接触)
if (inter.t > eps && inter.t < 1 - eps && inter.u > eps && inter.u < 1 - eps) {
return true
}
}
}
}
return false
},
// 根据线与边坡交点动态计算控制点;若一遍后仍有交叉,则把Y设为“比交点低10”,否则“低2”
getControlPointForCurve: function(point1, point2) {
// 找到线与边坡的交点
var intersectionPt = this.findIntersectionWithSlope(point1, point2)
var midX = (point1.x + point2.x) / 2
var midY = (point1.y + point2.y) / 2
// 无交点:控制点取中点
if (!intersectionPt) {
return { x: midX, y: midY }
}
// 基准Y:交点与两端点中的更大者(向下偏移)
var baseRefY = Math.max(intersectionPt.y, Math.max(point1.y, point2.y))
var smallOffset = 2 * this.dpr
var bigOffset = 12 * this.dpr
// 先尝试“低2像素”
var cpSmall = { x: midX, y: Math.max(midY, baseRefY + smallOffset) }
if (this.doesQuadraticCurveCrossBoundary(point1, cpSmall, point2)) {
// 仍与边坡有交叉:改为“低10像素”
return { x: midX, y: Math.max(midY, baseRefY + bigOffset) }
}
// 无交叉:使用“低2像素”
return cpSmall
}
}
return new cuCharts(ctn, data, opts)
},
mapOnload() {},
openRelieveAlarm(params, fn, close) {
var self = this
qf.UI.popupLayer({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment