为一条线保留平坦的 LineCap 属性,同时填充缺失的角
Retaining flat LineCap property for a line whilst filling in missing corners
我目前正在尝试使用给定坐标模拟铁路轨道。以前我一直在为 StrokeStart 和 StrokeEnd LineCap 属性 使用 'Rounded' 值,但是使用该值获得的增加的半径在添加轨道接头时会导致问题。我切换到 LineCap 的 'flat' 值,除了我的轨道的 'corners' 没有填充这一事实外,它的效果要好得多,如下所示:
缺角 https://imgur.com/a/EliIlzD
我试图通过首先使用 'Round' 值渲染我的所有曲目,然后使用 'Flat' 值再次渲染它们来抵消这种情况,这似乎确实填充了角落,但会导致其他问题,例如轨道被占用时颜色重叠,以及我首先渲染的圆形轨道出现在轨道末端:
颜色重叠 https://imgur.com/a/0XCVGv5
曲目结尾有问题 https://imgur.com/a/fKju9uA
我的 XAML 只是一条简单的线,由坐标列表和我的视图模型中的各种绑定组成,转换器可以稍微缩小我的坐标。这显然是首先使用 Rounded EndCaps 渲染的轨道:
<Line X1="{Binding X1, Converter={StaticResource ScaleXCoordConverter}}" Y1="{Binding Y1, Converter={StaticResource ScaleYCoordConverter}}"
X2="{Binding X2, Converter={StaticResource ScaleXCoordConverter}}" Y2="{Binding Y2, Converter={StaticResource ScaleYCoordConverter}}"
Stroke="{Binding DataContext.LineColor, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}"
StrokeThickness="2" StrokeEndLineCap="Round" StrokeStartLineCap="Round">
<Line.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DataContext.OccupyTrackCommand, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}"/>
</Line.InputBindings>
</Line>
有没有人幸运地创建了一条解决这些问题的自定义线,您可以在其中使用 LineCap 的 'Flat' 值,同时保留角落没有问题?编辑:为了澄清,我想我要求自定义实现线或线帽来解决所有这些问题,但非常欢迎任何其他解决方案。
我想出的解决方案非常适合我的项目,但我认为无论如何我都会 post 它以防将来遇到此线程的任何人有所帮助。
private void SetLineCaps() {
if (LineCoords.Count == 1) {
LineCoords[0].StartLineCap = "Flat";
LineCoords[0].EndLineCap = "Flat";
return;
}
foreach (var currentCoord in LineCoords) {
foreach (var compareCoord in LineCoords) {
if(currentCoord == compareCoord) continue;
if ((compareCoord.X1 == currentCoord.X1 && compareCoord.Y1 == currentCoord.Y1)
|| (compareCoord.X2 == currentCoord.X1 && compareCoord.Y2 == currentCoord.Y1)) {
currentCoord.StartLineCap = "Round";
}
if ((compareCoord.X1 == currentCoord.X2 && compareCoord.Y1 == currentCoord.Y2 )
|| (compareCoord.X2 == currentCoord.X2 && compareCoord.Y2 == currentCoord.Y2)){
currentCoord.EndLineCap = "Round";
}
}
}
}
基本上我最终要做的是检查每行的起点和终点,并检查起点或终点是否触及该特定行列表的任何其他点。例如,如果我有一个包含 3 条线的轨道,它会检查是否有任何线端接触,如果是,它会将特定线上限设置为 'Round',否则它会保持 'Flat' ].然后我将我的 StartLineCap 和 EndLineCap 限制为这些值,一切都按预期进行。如果您想了解我如何处理流血颜色,请参阅我关于 z-index 的其他 post。
我目前正在尝试使用给定坐标模拟铁路轨道。以前我一直在为 StrokeStart 和 StrokeEnd LineCap 属性 使用 'Rounded' 值,但是使用该值获得的增加的半径在添加轨道接头时会导致问题。我切换到 LineCap 的 'flat' 值,除了我的轨道的 'corners' 没有填充这一事实外,它的效果要好得多,如下所示:
缺角 https://imgur.com/a/EliIlzD
我试图通过首先使用 'Round' 值渲染我的所有曲目,然后使用 'Flat' 值再次渲染它们来抵消这种情况,这似乎确实填充了角落,但会导致其他问题,例如轨道被占用时颜色重叠,以及我首先渲染的圆形轨道出现在轨道末端:
颜色重叠 https://imgur.com/a/0XCVGv5
曲目结尾有问题 https://imgur.com/a/fKju9uA
我的 XAML 只是一条简单的线,由坐标列表和我的视图模型中的各种绑定组成,转换器可以稍微缩小我的坐标。这显然是首先使用 Rounded EndCaps 渲染的轨道:
<Line X1="{Binding X1, Converter={StaticResource ScaleXCoordConverter}}" Y1="{Binding Y1, Converter={StaticResource ScaleYCoordConverter}}"
X2="{Binding X2, Converter={StaticResource ScaleXCoordConverter}}" Y2="{Binding Y2, Converter={StaticResource ScaleYCoordConverter}}"
Stroke="{Binding DataContext.LineColor, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}"
StrokeThickness="2" StrokeEndLineCap="Round" StrokeStartLineCap="Round">
<Line.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding DataContext.OccupyTrackCommand, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}"/>
</Line.InputBindings>
</Line>
有没有人幸运地创建了一条解决这些问题的自定义线,您可以在其中使用 LineCap 的 'Flat' 值,同时保留角落没有问题?编辑:为了澄清,我想我要求自定义实现线或线帽来解决所有这些问题,但非常欢迎任何其他解决方案。
我想出的解决方案非常适合我的项目,但我认为无论如何我都会 post 它以防将来遇到此线程的任何人有所帮助。
private void SetLineCaps() {
if (LineCoords.Count == 1) {
LineCoords[0].StartLineCap = "Flat";
LineCoords[0].EndLineCap = "Flat";
return;
}
foreach (var currentCoord in LineCoords) {
foreach (var compareCoord in LineCoords) {
if(currentCoord == compareCoord) continue;
if ((compareCoord.X1 == currentCoord.X1 && compareCoord.Y1 == currentCoord.Y1)
|| (compareCoord.X2 == currentCoord.X1 && compareCoord.Y2 == currentCoord.Y1)) {
currentCoord.StartLineCap = "Round";
}
if ((compareCoord.X1 == currentCoord.X2 && compareCoord.Y1 == currentCoord.Y2 )
|| (compareCoord.X2 == currentCoord.X2 && compareCoord.Y2 == currentCoord.Y2)){
currentCoord.EndLineCap = "Round";
}
}
}
}
基本上我最终要做的是检查每行的起点和终点,并检查起点或终点是否触及该特定行列表的任何其他点。例如,如果我有一个包含 3 条线的轨道,它会检查是否有任何线端接触,如果是,它会将特定线上限设置为 'Round',否则它会保持 'Flat' ].然后我将我的 StartLineCap 和 EndLineCap 限制为这些值,一切都按预期进行。如果您想了解我如何处理流血颜色,请参阅我关于 z-index 的其他 post。