计算BricsCAD中折线对象的凸出系数

时间:2017-04-06 10:26:45

标签: c#

根据BULGE值的 DXF 说明(组代码42):

  

凸出(可选;默认为0)。凸起是四分之一的正切   弧段的夹角,如果弧线走,则为负   从起点到终点的顺时针方向。凸起为0表示   直线段,1的凸起是半圆形。

现在,我发现这个resource有关计算凸起的信息,但它适用于 lisp 编程。但是,它还部分说明:

  

使用数量定义折线弧段的曲率   被称为凸起。该单位测量曲线与曲线的偏差   连接段的两个顶点的直线(弦)。它是   定义为弧矢(常数)与长度的一半之比   两个顶点之间的和弦;这个比例等于   两者之间包含的弧角的四分之一的正切   折线顶点。

     

通过这种方式,负凸起表示   弧沿着从第一个顶点到下一个顶点的顺时针方向,   具有描述逆时针方向弧的正凸起。一个   凸起0表示直线段,凸起1表示a   半圆。

我正在C#中为 BricsCAD 编写例程并尝试使用凸起创建Polyline对象。我快到了:

目前,这是我构建顶点的方法。请注意,我正在取一个范围,然后将范围偏移一定边距。与此同时,我正在研究凸起值:

   Polyline oPolyRect = new Polyline();
    oPolyRect.AddVertexAt(0,
        new Point2d(extentsSelection3d.MinPoint.X - dMarginLeft, extentsSelection3d.MinPoint.Y), 0.0, 0.0, 0.0);
    oPolyRect.AddVertexAt(1,
        new Point2d(extentsSelection3d.MinPoint.X - dMarginLeft, extentsSelection3d.MaxPoint.Y), -0.5, 0.0, 0.0);
    oPolyRect.AddVertexAt(2,
        new Point2d(extentsSelection3d.MinPoint.X, extentsSelection3d.MaxPoint.Y + dMarginTop), 0.0, 0.0, 0.0);
    oPolyRect.AddVertexAt(3,
        new Point2d(extentsSelection3d.MaxPoint.X, extentsSelection3d.MaxPoint.Y + dMarginTop), -0.5, 0.0, 0.0);
    oPolyRect.AddVertexAt(4,
        new Point2d(extentsSelection3d.MaxPoint.X + dMarginRight, extentsSelection3d.MaxPoint.Y), 0.0, 0.0, 0.0);
    oPolyRect.AddVertexAt(5,
        new Point2d(extentsSelection3d.MaxPoint.X + dMarginRight, extentsSelection3d.MinPoint.Y), -0.5, 0.0, 0.0);
    oPolyRect.AddVertexAt(6,
        new Point2d(extentsSelection3d.MaxPoint.X, extentsSelection3d.MinPoint.Y - dMarginBottom), 0.0, 0.0, 0.0);
    oPolyRect.AddVertexAt(7,
        new Point2d(extentsSelection3d.MinPoint.X, extentsSelection3d.MinPoint.Y - dMarginBottom), -0.5, 0.0, 0.0);
    oPolyRect.AddVertexAt(8,
        new Point2d(extentsSelection3d.MinPoint.X - dMarginLeft, extentsSelection3d.MinPoint.Y), 0.0, 0.0, 0.0);

原则上它正在发挥作用。问题是凸起计算。我从空中挑出了-0.5,这还不够好。

Polyline对象还会公开SetBulgeAt方法,您可以在其中传递顶点索引和凸出因子。

任何人都可以告诉我如何将我发现的东西付诸实践,以便我有正确的膨胀因素吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

BricsSys向我提供了一个很好的答案:

here

我只复制了效果很好的C#代码:

public static class Extensions
{
        // Adds an arc (fillet) at each vertex, if able.
        public static void FilletAll(this Polyline pline, double radius)
    {
        int i = pline.Closed ? 0 : 1;
        for (int j = 0; j < pline.NumberOfVertices - i; j += 1 + pline.FilletAt(j, radius))
        { }
    }

    // Adds an arc (fillet) at the specified vertex. Returns 1 if the operation succeeded, 0 if it failed.
    public static int FilletAt(this Polyline pline, int index, double radius)
    {
        int prev = index == 0 && pline.Closed ? pline.NumberOfVertices - 1 : index - 1;

        if (pline.GetSegmentType(prev) != _AcDb.SegmentType.Line ||
          pline.GetSegmentType(index) != _AcDb.SegmentType.Line)
            return 0;

        LineSegment2d seg1 = pline.GetLineSegment2dAt(prev);
        LineSegment2d seg2 = pline.GetLineSegment2dAt(index);

        Vector2d vec1 = seg1.StartPoint - seg1.EndPoint;
        Vector2d vec2 = seg2.EndPoint - seg2.StartPoint;

        double angle = (Math.PI - vec1.GetAngleTo(vec2)) / 2.0;
        double dist = radius * Math.Tan(angle);
        if (dist > seg1.Length || dist > seg2.Length)
            return 0;

        Point2d pt1 = seg1.EndPoint + vec1.GetNormal() * dist;
        Point2d pt2 = seg2.StartPoint + vec2.GetNormal() * dist;

        double bulge = Math.Tan(angle / 2.0);
        if (Clockwise(seg1.StartPoint, seg1.EndPoint, seg2.EndPoint))
            bulge = -bulge;

        pline.AddVertexAt(index, pt1, bulge, 0.0, 0.0);
        pline.SetPointAt(index + 1, pt2);

        return 1;
    }

        // Evaluates if the points are clockwise.
        private static bool Clockwise(Point2d p1, Point2d p2, Point2d p3)
    {
        return ((p2.X - p1.X) * (p3.Y - p1.Y) - (p2.Y - p1.Y) * (p3.X - p1.X)) < 1e-8;
    }
}