Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
V
V3-TailingPond
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xinzhedeai
V3-TailingPond
Commits
a695183b
Commit
a695183b
authored
Oct 23, 2025
by
sxl
💬
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix:水位线坐标调整
parent
61b11b3a
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
456 additions
and
103 deletions
+456
-103
index.vue
src/views/Screen/index.vue
+456
-103
No files found.
src/views/Screen/index.vue
View file @
a695183b
...
@@ -1079,7 +1079,7 @@ export default {
...
@@ -1079,7 +1079,7 @@ export default {
sx
:
holeX
,
sx
:
holeX
,
sy
:
ladderSY
,
sy
:
ladderSY
,
ex
:
holeX
,
ex
:
holeX
,
ey
:
holeEndY
,
ey
:
holeEndY
+
device
.
holeBaseElevation
,
// 控制穿孔线的长度
width
:
lineW
,
width
:
lineW
,
color
:
'
grey
'
color
:
'
grey
'
})
})
...
@@ -1088,15 +1088,16 @@ export default {
...
@@ -1088,15 +1088,16 @@ export default {
var
deviceSY
=
deviceEY
-
deviceH
var
deviceSY
=
deviceEY
-
deviceH
this
.
drawLiner
({
this
.
drawLiner
({
sx
:
holeX
,
sx
:
holeX
,
sy
:
deviceSY
,
sy
:
deviceSY
+
device
.
holeBaseElevation
,
ex
:
holeX
,
ex
:
holeX
,
ey
:
deviceEY
,
ey
:
deviceEY
+
device
.
holeBaseElevation
,
width
:
deviceW
,
width
:
deviceW
,
color
:
'
#3403CB
'
color
:
'
#3403CB
'
})
})
// 水位值的x,y坐标
this
.
options
.
deviceCoords
.
push
({
this
.
options
.
deviceCoords
.
push
({
x
:
holeX
,
x
:
holeX
,
y
:
deviceLY
,
y
:
deviceLY
+
device
.
holeBaseElevation
,
stepY
:
ladderSY
stepY
:
ladderSY
})
})
var
valFont
=
11
var
valFont
=
11
...
@@ -1105,7 +1106,7 @@ export default {
...
@@ -1105,7 +1106,7 @@ export default {
this
.
drawText
({
this
.
drawText
({
x
:
holeX
,
x
:
holeX
,
y
:
valueSY
,
y
:
valueSY
+
device
.
holeBaseElevation
,
size
:
valFont
,
size
:
valFont
,
text
:
text
,
text
:
text
,
color
:
'
white
'
,
color
:
'
white
'
,
...
@@ -1113,50 +1114,44 @@ export default {
...
@@ -1113,50 +1114,44 @@ export default {
})
})
}
}
// 连接所有水位值,只在首尾延长
// 连接所有水位值,
使用曲线连接,
只在首尾延长
var
deviceCoords
=
this
.
options
.
deviceCoords
||
[]
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 计算的,可能需要排序)
// 按X坐标从左到右排序(因为设备X坐标是 endX - device.x 计算的,可能需要排序)
deviceCoords
.
sort
(
function
(
a
,
b
)
{
deviceCoords
.
sort
(
function
(
a
,
b
)
{
return
a
.
x
-
b
.
x
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
)
{
if
(
deviceCoords
.
length
>=
2
)
{
// 计算延伸距离(可以根据需要调整)
// 计算延伸距离(可以根据需要调整)
var
extensionLength
=
30
*
this
.
dpr
// 延伸30像素
var
extensionLength
=
30
*
this
.
dpr
// 延伸30像素
// 连接所有相邻的水位点
// 准备曲线点数组
for
(
var
i
=
0
;
i
<
deviceCoords
.
length
-
1
;
i
++
)
{
var
curvePoints
=
[]
var
currentDevice
=
deviceCoords
[
i
]
var
needCurveConnection
=
false
// 标记是否需要曲线连接
var
nextDevice
=
deviceCoords
[
i
+
1
]
// 只绘制设备之间的连线,不延伸
this
.
drawLiner
({
sx
:
currentDevice
.
x
,
sy
:
currentDevice
.
y
,
ex
:
nextDevice
.
x
,
ey
:
nextDevice
.
y
,
width
:
2
,
color
:
'
blue
'
})
}
//
只在第一个和最后一个水位值点处理延伸线
//
处理左侧延伸点
var
firstDevice
=
deviceCoords
[
0
]
var
firstDevice
=
deviceCoords
[
0
]
var
lastDevice
=
deviceCoords
[
deviceCoords
.
length
-
1
]
var
secondDevice
=
deviceCoords
[
1
]
var
secondDevice
=
deviceCoords
[
1
]
var
secondLastDevice
=
deviceCoords
[
deviceCoords
.
length
-
2
]
var
chartMinX
=
this
.
options
.
initX
var
chartMinX
=
this
.
options
.
initX
var
chartMaxX
=
this
.
options
.
endX
var
chartMaxX
=
this
.
options
.
endX
var
chartMinY
=
this
.
options
.
initY
var
chartMinY
=
this
.
options
.
initY
var
chartMaxY
=
this
.
options
.
endY
var
chartMaxY
=
this
.
options
.
endY
var
shrinkDistance
=
1
0
*
this
.
dpr
var
shrinkDistance
=
1
5
*
this
.
dpr
// 安全距离 15px
// 处理第一个点的左侧延伸线
// 计算左侧延伸点
// 判断:如果第一个和第二个X坐标相同,则不绘制延伸线
if
(
firstDevice
&&
secondDevice
&&
Math
.
abs
(
firstDevice
.
x
-
secondDevice
.
x
)
>
1
)
{
if
(
firstDevice
&&
secondDevice
&&
Math
.
abs
(
firstDevice
.
x
-
secondDevice
.
x
)
>
1
)
{
var
dx1
=
secondDevice
.
x
-
firstDevice
.
x
var
dx1
=
secondDevice
.
x
-
firstDevice
.
x
var
dy1
=
secondDevice
.
y
-
firstDevice
.
y
var
dy1
=
secondDevice
.
y
-
firstDevice
.
y
...
@@ -1171,27 +1166,29 @@ export default {
...
@@ -1171,27 +1166,29 @@ export default {
startX
=
Math
.
max
(
chartMinX
,
Math
.
min
(
chartMaxX
,
startX
))
startX
=
Math
.
max
(
chartMinX
,
Math
.
min
(
chartMaxX
,
startX
))
startY
=
Math
.
max
(
chartMinY
,
Math
.
min
(
chartMaxY
,
startY
))
startY
=
Math
.
max
(
chartMinY
,
Math
.
min
(
chartMaxY
,
startY
))
// 如果启用边界限制,找到延伸线与边坡线的交点
// 如果启用边界限制,找到延伸线与边坡线的交点
(按y最小选择)
if
(
this
.
options
.
enableBoundaryLimit
&&
this
.
bianpoLinePoinArr
.
length
>
0
)
{
if
(
this
.
options
.
enableBoundaryLimit
&&
this
.
bianpoLinePoinArr
.
length
>
0
)
{
var
leftIntersections
=
[]
var
leftIntersections
=
[]
for
(
var
j
=
0
;
j
<
this
.
bianpoLinePoinArr
.
length
-
1
;
j
++
)
{
for
(
var
m
=
0
;
m
<
this
.
bianpoLinePoinArr
.
length
-
1
;
m
++
)
{
var
slopePoint1
=
this
.
bianpoLinePoinArr
[
j
]
var
slopePoint1
=
this
.
bianpoLinePoinArr
[
m
]
var
slopePoint2
=
this
.
bianpoLinePoinArr
[
j
+
1
]
var
slopePoint2
=
this
.
bianpoLinePoinArr
[
m
+
1
]
var
leftIntersection
=
this
.
getLineIntersection
(
var
interL
=
this
.
getLineIntersection
(
firstDevice
.
x
,
firstDevice
.
y
,
startX
,
startY
,
firstDevice
.
x
,
firstDevice
.
y
,
startX
,
startY
,
slopePoint1
.
x
,
slopePoint1
.
y
,
slopePoint2
.
x
,
slopePoint2
.
y
slopePoint1
.
x
,
slopePoint1
.
y
,
slopePoint2
.
x
,
slopePoint2
.
y
)
)
if
(
leftIntersection
)
{
if
(
interL
&&
interL
.
t
>=
0
&&
interL
.
t
<=
1
&&
interL
.
u
>=
0
&&
interL
.
u
<=
1
)
{
leftIntersections
.
push
(
leftIntersection
)
leftIntersections
.
push
(
interL
)
}
}
}
}
if
(
leftIntersections
.
length
>
0
)
{
if
(
leftIntersections
.
length
>
0
)
{
var
closestLeft
=
leftIntersections
.
reduce
((
closest
,
current
)
=>
{
// 选择y最小(更靠上)的交点,若并列取t最小
var
closestDist
=
Math
.
abs
(
closest
.
x
-
firstDevice
.
x
)
var
closestLeft
=
leftIntersections
.
reduce
(
function
(
best
,
cur
)
{
var
currentDist
=
Math
.
abs
(
current
.
x
-
firstDevice
.
x
)
if
(
!
best
)
return
cur
return
currentDist
<
closestDist
?
current
:
closest
if
(
cur
.
y
<
best
.
y
-
1
e
-
6
)
return
cur
})
if
(
Math
.
abs
(
cur
.
y
-
best
.
y
)
<=
1
e
-
6
)
return
(
cur
.
t
<
best
.
t
?
cur
:
best
)
return
best
},
null
)
var
leftDx
=
firstDevice
.
x
-
closestLeft
.
x
var
leftDx
=
firstDevice
.
x
-
closestLeft
.
x
var
leftDy
=
firstDevice
.
y
-
closestLeft
.
y
var
leftDy
=
firstDevice
.
y
-
closestLeft
.
y
var
leftLength
=
Math
.
sqrt
(
leftDx
*
leftDx
+
leftDy
*
leftDy
)
var
leftLength
=
Math
.
sqrt
(
leftDx
*
leftDx
+
leftDy
*
leftDy
)
...
@@ -1200,6 +1197,7 @@ export default {
...
@@ -1200,6 +1197,7 @@ export default {
var
leftUnitY
=
leftDy
/
leftLength
var
leftUnitY
=
leftDy
/
leftLength
startX
=
closestLeft
.
x
+
leftUnitX
*
shrinkDistance
startX
=
closestLeft
.
x
+
leftUnitX
*
shrinkDistance
startY
=
closestLeft
.
y
+
leftUnitY
*
shrinkDistance
startY
=
closestLeft
.
y
+
leftUnitY
*
shrinkDistance
needCurveConnection
=
true
// 标记需要曲线连接
}
else
{
}
else
{
startX
=
closestLeft
.
x
startX
=
closestLeft
.
x
startY
=
closestLeft
.
y
startY
=
closestLeft
.
y
...
@@ -1207,19 +1205,17 @@ export default {
...
@@ -1207,19 +1205,17 @@ export default {
}
}
}
}
// 绘制第一个点的左侧延伸线
curvePoints
.
push
({
x
:
startX
,
y
:
startY
})
this
.
drawLiner
({
sx
:
startX
,
sy
:
startY
,
ex
:
firstDevice
.
x
,
ey
:
firstDevice
.
y
,
width
:
2
,
color
:
'
blue
'
})
}
}
// 处理最后一个点的右侧延伸线
// 添加所有设备点
// 判断:如果最后一个和倍数第二个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
)
{
if
(
lastDevice
&&
secondLastDevice
&&
Math
.
abs
(
lastDevice
.
x
-
secondLastDevice
.
x
)
>
1
)
{
var
dx2
=
lastDevice
.
x
-
secondLastDevice
.
x
var
dx2
=
lastDevice
.
x
-
secondLastDevice
.
x
var
dy2
=
lastDevice
.
y
-
secondLastDevice
.
y
var
dy2
=
lastDevice
.
y
-
secondLastDevice
.
y
...
@@ -1227,58 +1223,114 @@ export default {
...
@@ -1227,58 +1223,114 @@ export default {
var
unitX2
=
dx2
/
length2
var
unitX2
=
dx2
/
length2
var
unitY2
=
dy2
/
length2
var
unitY2
=
dy2
/
length2
var
e
ndX
=
lastDevice
.
x
+
unitX2
*
extensionLength
var
rightE
ndX
=
lastDevice
.
x
+
unitX2
*
extensionLength
var
e
ndY
=
lastDevice
.
y
+
unitY2
*
extensionLength
var
rightE
ndY
=
lastDevice
.
y
+
unitY2
*
extensionLength
// 限制终点坐标
// 限制终点坐标
endX
=
Math
.
max
(
chartMinX
,
Math
.
min
(
chartMaxX
,
e
ndX
))
rightEndX
=
Math
.
max
(
chartMinX
,
Math
.
min
(
chartMaxX
,
rightE
ndX
))
endY
=
Math
.
max
(
chartMinY
,
Math
.
min
(
chartMaxY
,
e
ndY
))
rightEndY
=
Math
.
max
(
chartMinY
,
Math
.
min
(
chartMaxY
,
rightE
ndY
))
// 如果启用边界限制,找到延伸线与边坡线的交点
// 如果启用边界限制,找到延伸线与边坡线的交点
(按y最小选择)
if
(
this
.
options
.
enableBoundaryLimit
&&
this
.
bianpoLinePoinArr
.
length
>
0
)
{
if
(
this
.
options
.
enableBoundaryLimit
&&
this
.
bianpoLinePoinArr
.
length
>
0
)
{
var
rightIntersections
=
[]
var
rightIntersections
=
[]
for
(
var
j
=
0
;
j
<
this
.
bianpoLinePoinArr
.
length
-
1
;
j
++
)
{
for
(
var
n
=
0
;
n
<
this
.
bianpoLinePoinArr
.
length
-
1
;
n
++
)
{
var
slopePoint1
=
this
.
bianpoLinePoinArr
[
j
]
var
slopePoint1
=
this
.
bianpoLinePoinArr
[
n
]
var
slopePoint2
=
this
.
bianpoLinePoinArr
[
j
+
1
]
var
slopePoint2
=
this
.
bianpoLinePoinArr
[
n
+
1
]
var
rightIntersection
=
this
.
getLineIntersection
(
var
interR
=
this
.
getLineIntersection
(
lastDevice
.
x
,
lastDevice
.
y
,
endX
,
e
ndY
,
lastDevice
.
x
,
lastDevice
.
y
,
rightEndX
,
rightE
ndY
,
slopePoint1
.
x
,
slopePoint1
.
y
,
slopePoint2
.
x
,
slopePoint2
.
y
slopePoint1
.
x
,
slopePoint1
.
y
,
slopePoint2
.
x
,
slopePoint2
.
y
)
)
if
(
rightIntersection
)
{
if
(
interR
&&
interR
.
t
>=
0
&&
interR
.
t
<=
1
&&
interR
.
u
>=
0
&&
interR
.
u
<=
1
)
{
rightIntersections
.
push
(
rightIntersection
)
rightIntersections
.
push
(
interR
)
}
}
}
}
if
(
rightIntersections
.
length
>
0
)
{
if
(
rightIntersections
.
length
>
0
)
{
var
closestRight
=
rightIntersections
.
reduce
((
closest
,
current
)
=>
{
var
closestRight
=
rightIntersections
.
reduce
(
function
(
best
,
cur
)
{
var
closestDist
=
Math
.
abs
(
closest
.
x
-
lastDevice
.
x
)
if
(
!
best
)
return
cur
var
currentDist
=
Math
.
abs
(
current
.
x
-
lastDevice
.
x
)
if
(
cur
.
y
<
best
.
y
-
1
e
-
6
)
return
cur
return
currentDist
<
closestDist
?
current
:
closest
if
(
Math
.
abs
(
cur
.
y
-
best
.
y
)
<=
1
e
-
6
)
return
(
cur
.
t
<
best
.
t
?
cur
:
best
)
})
return
best
},
null
)
var
rightDx
=
lastDevice
.
x
-
closestRight
.
x
var
rightDx
=
lastDevice
.
x
-
closestRight
.
x
var
rightDy
=
lastDevice
.
y
-
closestRight
.
y
var
rightDy
=
lastDevice
.
y
-
closestRight
.
y
var
rightLength
=
Math
.
sqrt
(
rightDx
*
rightDx
+
rightDy
*
rightDy
)
var
rightLength
=
Math
.
sqrt
(
rightDx
*
rightDx
+
rightDy
*
rightDy
)
if
(
rightLength
>
0
)
{
if
(
rightLength
>
0
)
{
var
rightUnitX
=
rightDx
/
rightLength
var
rightUnitX
=
rightDx
/
rightLength
var
rightUnitY
=
rightDy
/
rightLength
var
rightUnitY
=
rightDy
/
rightLength
endX
=
closestRight
.
x
+
rightUnitX
*
shrinkDistance
rightEndX
=
closestRight
.
x
+
rightUnitX
*
shrinkDistance
endY
=
closestRight
.
y
+
rightUnitY
*
shrinkDistance
rightEndY
=
closestRight
.
y
+
rightUnitY
*
shrinkDistance
needCurveConnection
=
true
// 标记需要曲线连接
}
else
{
}
else
{
e
ndX
=
closestRight
.
x
rightE
ndX
=
closestRight
.
x
e
ndY
=
closestRight
.
y
rightE
ndY
=
closestRight
.
y
}
}
}
}
}
}
// 绘制最后一个点的右侧延伸线
curvePoints
.
push
({
x
:
rightEndX
,
y
:
rightEndY
})
this
.
drawLiner
({
}
sx
:
lastDevice
.
x
,
sy
:
lastDevice
.
y
,
// 两点之閴的直线是否穿过边坡,穿过则用曲线,其余用直线;两端延长线用直线
ex
:
endX
,
if
(
curvePoints
.
length
>=
2
)
{
ey
:
endY
,
var
ctx
=
this
.
ctx
width
:
2
,
ctx
.
lineWidth
=
2
color
:
'
blue
'
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 {
...
@@ -1551,7 +1603,8 @@ export default {
holeDepth
:
item
.
jrx_trepanning
,
holeDepth
:
item
.
jrx_trepanning
,
value
:
item
.
depth
,
value
:
item
.
depth
,
depth
:
item
.
jrx_burial
,
depth
:
item
.
jrx_burial
,
waterValue
:
item
.
stage
waterValue
:
item
.
stage
,
holeBaseElevation
:
item
.
holeBaseElevation
})
})
}
}
return
arr
return
arr
...
@@ -1599,25 +1652,104 @@ export default {
...
@@ -1599,25 +1652,104 @@ export default {
ctx
.
strokeStyle
=
o
.
color
ctx
.
strokeStyle
=
o
.
color
ctx
.
stroke
()
ctx
.
stroke
()
},
},
// 计算两条线段的交点
// 新增:绘制曲线方法
getLineIntersection
:
function
(
x1
,
y1
,
x2
,
y2
,
x3
,
y3
,
x4
,
y4
)
{
drawCurve
:
function
(
points
,
width
,
color
)
{
const
denom
=
(
x1
-
x2
)
*
(
y3
-
y4
)
-
(
y1
-
y2
)
*
(
x3
-
x4
)
if
(
!
points
||
points
.
length
<
2
)
return
if
(
Math
.
abs
(
denom
)
<
1
e
-
10
)
{
return
null
// 平行线,无交点
}
const
t
=
((
x1
-
x3
)
*
(
y3
-
y4
)
-
(
y1
-
y3
)
*
(
x3
-
x4
))
/
denom
const
u
=
-
((
x1
-
x2
)
*
(
y1
-
y3
)
-
(
y1
-
y2
)
*
(
x1
-
x3
))
/
denom
// 检查交点是否在两条线段上
var
ctx
=
this
.
ctx
if
(
t
>=
0
&&
t
<=
1
&&
u
>=
0
&&
u
<=
1
)
{
ctx
.
beginPath
()
return
{
ctx
.
lineWidth
=
width
||
2
x
:
x1
+
t
*
(
x2
-
x1
),
ctx
.
strokeStyle
=
color
||
'
blue
'
y
:
y1
+
t
*
(
y2
-
y1
)
// 如果只有两个点,绘制简单的曲线
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
)
}
}
}
}
}
return
null
// 无交点
ctx
.
stroke
()
},
// 计算两条线段的交点(数值稳定,返回x,y并附带t/u,含共线重叠处理)
getLineIntersection
:
function
(
x1
,
y1
,
x2
,
y2
,
x3
,
y3
,
x4
,
y4
)
{
const
eps
=
1
e
-
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
}
// 对应第二段的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
}
}
// 一般情况
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
)
{
drawText
:
function
(
o
)
{
var
ctx
=
this
.
ctx
var
ctx
=
this
.
ctx
...
@@ -1738,13 +1870,17 @@ export default {
...
@@ -1738,13 +1870,17 @@ export default {
},
},
// 新增:检查水位线是否在边坡线上方或外部
// 新增:检查水位线是否在边坡线上方或外部
checkIfWaterLineAboveSlope
:
function
(
currentDevice
,
nextDevice
)
{
checkIfWaterLineAboveSlope
:
function
(
currentDevice
,
nextDevice
)
{
// 检查水位线的起点和终点是否在边坡线范围内
// 计算边坡X范围(取最小/最大,避免采样顺序影响)
var
slopeStartX
=
this
.
bianpoLinePoinArr
[
0
].
x
var
minX
=
Infinity
;
var
maxX
=
-
Infinity
var
slopeEndX
=
this
.
bianpoLinePoinArr
[
this
.
bianpoLinePoinArr
.
length
-
1
].
x
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范围,认为在边坡外部
// 如果水位线的任一端点超出边坡线的X范围,认为在边坡外部
if
(
currentDevice
.
x
<
slopeStartX
||
currentDevice
.
x
>
slopeEnd
X
||
if
(
currentDevice
.
x
<
minX
||
currentDevice
.
x
>
max
X
||
nextDevice
.
x
<
slopeStartX
||
nextDevice
.
x
>
slopeEnd
X
)
{
nextDevice
.
x
<
minX
||
nextDevice
.
x
>
max
X
)
{
console
.
log
(
'
水位线超出边坡X范围
'
)
console
.
log
(
'
水位线超出边坡X范围
'
)
return
true
return
true
}
}
...
@@ -1793,12 +1929,229 @@ export default {
...
@@ -1793,12 +1929,229 @@ export default {
}
}
return
null
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
}
}
return
new
cuCharts
(
ctn
,
data
,
opts
)
var
eps
=
1
e
-
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
=
1
e
-
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
}
}
}
mapOnload
()
{},
return
best
},
// 新增:判断两点的直线连接是否会穿过边坡(优先精确判断,采样兜底)
isLineSegmentCrossesBoundary
:
function
(
point1
,
point2
)
{
if
(
!
this
.
bianpoLinePoinArr
||
this
.
bianpoLinePoinArr
.
length
<
2
)
{
return
false
// 没有边界数据,默认不穿过
}
// 1) 精确判断与任何边坡线段是否相交
var
eps
=
1
e
-
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
=
1
e
-
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
)
},
openRelieveAlarm
(
params
,
fn
,
close
)
{
openRelieveAlarm
(
params
,
fn
,
close
)
{
var
self
=
this
var
self
=
this
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment