我无法渲染WPF ArcSegment。笔触颜色不起作用

时间:2017-10-15 22:11:08

标签: c# wpf

我试图使用ArcSegment将模型的一部分渲染为半圆。我的代码使用了许多基于2D路径的对象。除了使用ArcSegment的模块外,所有工作都正常。例如,使用LineSegment的类似模块可以正常工作。

我可以看到我的ArcSegment的基本几何图形是正确的,因为Fill属性通过填充预期半圆内的区域来使弧可见。

我没有使用XAML。所有形状都是使用C#/ WPF函数构建的。

以下是使用WPF Path对象渲染所有Geometry对象的代码:

        // builder constructs a collection of Geometry objects and returns the in a GeometryGroup via ToGeometry()
        GeometryGroup model2D = builder.ToGeometry();

        model2D.Transform = BuildLocalTransform2D(visualModel);
        var visual2D = new System.Windows.Shapes.Path();

        if (typeof(Foundation.Visualisation.Elements2D.ShapeElement).IsAssignableFrom(visualModel.GetType()))
            visual2D.Fill = ((Foundation.Visualisation.Elements2D.ShapeElement)visualModel).ShapeStyle.BackgroundBrush;
        else
            // ArcSegment and LineSegment based geometries always follow this path
            // was using transparent but needed to add a color to make ArcSegment based Path visible
            // the assignment to Stroke below does not work (line remains transparent) when model2D contains a PathGeometry that contains one ArcSegment
            // I can see that the arc has the correct shape when the fill is not transparent
            //visual2D.Fill = Brushes.Transparent;
            visual2D.Fill = Brushes.Cyan;

        // debug shows StrokeThickness is always 2
        visual2D.StrokeThickness = ((PathElement)visualModel).LineStyle.LineThickness;
        // debug shows that Stroke is always Brushes.Black
        visual2D.Stroke = ((PathElement)visualModel).LineStyle.LineBrush;
        visual2D.StrokeStartLineCap = PenLineCap.Round;
        visual2D.StrokeEndLineCap = PenLineCap.Round;
        visual2D.StrokeLineJoin = PenLineJoin.Round;

        visual2D.Data = model2D;

        WpfVisual2DProxy node = new WpfVisual2DProxy(visual2D, visualModel);
        visualModel.AddProxy(node);

        // the following adds the visual to an ItemsControl using a Canvas based template:
        //  this.ItemsPanel = new ItemsPanelTemplate(new FrameworkElementFactory(typeof(Canvas)));     
        ((VisualContainer)((WpfVisual2DProxy)parentNode).Visual2D).AddChild(visual2D);

以下是我用来创建ArcSegment的代码:

    public void AddArc(ModelPoint2D arcStart, ModelPoint2D arcEnd, double ellipseFactor, double degrees, bool isLarge, SweepDirection sweepDirection, LineVisualStyle lineStyle)
    {
        double radius = ellipseFactor * arcStart.Distance(arcEnd) / 2.0;
        List<ArcSegment> list = new List<ArcSegment>(2);
        Point start = converter.ToPoint2D(arcStart);           
        list.Add(new ArcSegment(converter.ToPoint2D(arcEnd), new Size(radius, radius), Extrusion.DegreesToRadians(degrees), isLarge, SweepDirection.Clockwise, false));            
        var pathFigure = new PathFigure(start, list, false);
        var pfList = new List<PathFigure>(1);
        pfList.Add(pathFigure);

        group.Children.Add(new PathGeometry(pfList));
    }

此处生成的几何体始终具有透明笔划,但可以使用“填充”属性使圆弧可见。

下面是我用来创建半圆形等效半径的代码:

    public void AddPath(IList<ModelPoint2D> Points, LineVisualStyle lineStyle)
    {
        List<LineSegment> list = new List<LineSegment>(Points.Count);
        Point start = converter.ToPoint2D(Points[0]);
        for (int i = 1; i < Points.Count; i++)
        {
            list.Add(new LineSegment(converter.ToPoint2D(Points[i]), true));
        }
        var pathFigure = new PathFigure(start, list, false);
        var pfList = new List<PathFigure>(1);
        pfList.Add(pathFigure);
        group.Children.Add(new PathGeometry(pfList));
    }

使用LineSegment的代码会产生一个响应笔画和填充设置的几何。

结果渲染如下所示:

The Semicircle at the top has Fill visible but not Stroke

我尝试了很多组合,包括将PathGeometry直接添加到Path.Data而不是包装在GeometryGroup中。

非常感谢任何建议/协助。

请求的VisualModel代码如下:

public abstract class VisualModel
{
    /// <summary>
    /// Recursive hierarchy of VisualModel objects that describe the visual structure of an entity for a specific ViewportType.
    /// The top level of the hierarchy is owned by EntityViews via a ViewportTypeVisualModel entry
    /// </summary>
    /// <param name="id">An optional model component identifier - useful for debug</param>
    public VisualModel(string id)
    {
        domainBindings = null;
        proxies = null;
        Id = id;
        ParentVisualModel = null;
        LocalTransforms = null;
        IsStatic = true;
    }

    public bool HasDomainBindings
    {
        get
        {
            if (domainBindings == null)
                return false;
            return domainBindings.Count > 0;
        }
    }

    public bool HasProxies
    {
        get
        {
            if (proxies == null)
                return false;
            return proxies.Count > 0;
        }
    }

    public string Id { get; private set; }

    /// <summary>
    /// Static objects are not affected by transforms that change after the render is constructed.
    /// Non-Static (Dynamic) objects have transforms that may be changed by the application after the render is constructed
    /// Dynamic objects have attached event handlers that adjust the transforms in response to application events
    /// </summary>
    public bool IsStatic { get; private set; }

    public List<TransformBase> LocalTransforms { get; private set; }

    public VisualModel ParentVisualModel { get; internal set; }

    public void AddDomainBinding(BindingBase binding)
    {
        DomainBindings.Add(binding);
    }

    public void AddLocalTransform(TransformBase transform)
    {
        if (LocalTransforms == null)
            LocalTransforms = new List<TransformBase>(4);
        LocalTransforms.Add(transform);
        if (transform.IsDynamic)
            IsStatic = false;
    }

    public void AddProxy(VisualProxy visualProxy)
    {
        Proxies.Add(visualProxy);
    }

    protected List<BindingBase> DomainBindings
    {
        get
        {
            if (domainBindings == null)
                domainBindings = new List<BindingBase>();
            return domainBindings;
        }
    }

    protected List<VisualProxy> Proxies
    {
        get
        {
            if (proxies == null)
                proxies = new List<VisualProxy>();
            return proxies;
        }
    }

    public virtual void UnbindAll()
    {
        if (domainBindings == null)
            return;
        foreach (BindingBase binding in this.DomainBindings)
            binding.UnBind();
    }

    private List<BindingBase> domainBindings;
    private List<VisualProxy> proxies;
}

请注意,VisualModel表示图形/渲染技术不可知模型容器。它包含的VisualProxy对象是特定于技术的图形对象的基类。在这种情况下,WpfVisual2DProxy对象包装包含我的WPF可渲染表示的WPF UIElement对象。

以下是VisualProxy:

public abstract class VisualProxy
{
    public VisualModel.VisualModel VisualModel { get; private set; }
    public VisualProxy Parent { get; private set; }

    public VisualProxy(VisualModel.VisualModel visualModel)
    {
        VisualModel = visualModel;
        Parent = null;
    }

    public VisualProxy(VisualModel.VisualModel visualModel, VisualProxy parent)
    {
        VisualModel = visualModel;
        Parent = parent;
    }
}

以下是WpfVisual2DProxy:

public class WpfVisual2DProxy : VisualProxy
{
    public UIElement Visual2D { get; private set; }

    public WpfVisual2DProxy(UIElement visual2D, VisualModel visualModel) : base(visualModel)
    {
        Visual2D = visual2D;
    }

    public WpfVisual2DProxy(UIElement visual2D, VisualModel visualModel, WpfVisual2DProxy parent) : base(visualModel, parent)
    {
        Visual2D = visual2D;
    }
}

1 个答案:

答案 0 :(得分:0)

非常感谢所有想到我的问题的人。

克莱门斯是对的。我的ArcSegment上没有将isStroked设置为true。

令人尴尬的简单。

谢谢