惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

U
Unit 42
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Y
Y Combinator Blog
G
Google Developers Blog
Vercel News
Vercel News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Jina AI
Jina AI
Blog — PlanetScale
Blog — PlanetScale
H
Help Net Security
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
阮一峰的网络日志
阮一峰的网络日志
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
T
Tailwind CSS Blog
博客园 - 叶小钗
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
Microsoft Security Blog
Microsoft Security Blog
P
Proofpoint News Feed
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw
三维图元系统
我才是银古 · 2026-06-19 · via 博客园 - 我才是银古

第七章:三维图元系统

7.1 三维图元概述

7.1.1 三维图元分类

LightCAD的三维图元位于LightCAD.Core/Elements/Element3d/目录下,提供了完整的三维空间几何实体支持:

图元类型 类名 说明
三维直线 LcLine3d 三维空间中的线段
三维圆弧 LcArc3d 三维空间中的圆弧
三维圆 LcCircle3d 三维空间中的圆
三维曲线 LcCurve3d 通用三维曲线
三维轮廓 LcProfile3d 用于拉伸等操作的截面轮廓
工作平面 LcWorkPlane3d 自定义工作坐标系
三维组 LcGroup3 三维实体的分组容器
三维阵列 LcArray3 三维空间中的阵列复制
容器引用 LcContianerRef3 组件容器引用

7.1.2 二维与三维图元的关系

二维图元(在XY平面上)        三维图元(在任意空间位置)
LcLine    ──对应──>    LcLine3d
LcArc     ──对应──>    LcArc3d
LcCircle  ──对应──>    LcCircle3d
LcSpline  ──对应──>    LcCurve3d

三维图元在二维图元的基础上增加了Z坐标和空间方位信息,能够表示任意空间位置和方向的几何实体。

7.2 三维直线(LcLine3d)

7.2.1 数据结构

public class LcLine3d : LcEntity, IUpdateObject
{
    /// <summary>
    /// 起点(三维坐标)
    /// </summary>
    public Point3d StartPoint { get; set; }

    /// <summary>
    /// 终点(三维坐标)
    /// </summary>
    public Point3d EndPoint { get; set; }

    /// <summary>
    /// 长度
    /// </summary>
    public double Length => StartPoint.DistanceTo(EndPoint);

    /// <summary>
    /// 方向向量
    /// </summary>
    public Vector3d Direction =>
        new Vector3d(
            EndPoint.X - StartPoint.X,
            EndPoint.Y - StartPoint.Y,
            EndPoint.Z - StartPoint.Z
        ).Normalize();

    /// <summary>
    /// 中点
    /// </summary>
    public Point3d MidPoint => new Point3d(
        (StartPoint.X + EndPoint.X) / 2,
        (StartPoint.Y + EndPoint.Y) / 2,
        (StartPoint.Z + EndPoint.Z) / 2
    );

    public override string TypeName => "Line3d";

    /// <summary>
    /// 投影到XY平面获取二维线段
    /// </summary>
    public LcLine ToLine2d()
    {
        return new LcLine
        {
            StartPoint = StartPoint.ToPoint2d(),
            EndPoint = EndPoint.ToPoint2d()
        };
    }

    /// <summary>
    /// 计算点到三维直线的距离
    /// </summary>
    public double DistanceTo3d(Point3d point)
    {
        var ab = new Vector3d(
            EndPoint.X - StartPoint.X,
            EndPoint.Y - StartPoint.Y,
            EndPoint.Z - StartPoint.Z);
        var ap = new Vector3d(
            point.X - StartPoint.X,
            point.Y - StartPoint.Y,
            point.Z - StartPoint.Z);

        var cross = ab.Cross(ap);
        return cross.Length / ab.Length;
    }

    public override void TransformBy(Matrix4d matrix)
    {
        StartPoint = matrix.Transform(StartPoint);
        EndPoint = matrix.Transform(EndPoint);
    }
}

7.2.2 使用示例

// 创建一条在三维空间中的直线
var line3d = new LcLine3d
{
    StartPoint = new Point3d(0, 0, 0),
    EndPoint = new Point3d(100, 50, 75)
};

// 获取直线信息
Console.WriteLine($"长度: {line3d.Length}");
Console.WriteLine($"方向: {line3d.Direction}");
Console.WriteLine($"中点: {line3d.MidPoint}");

// 投影到二维
var line2d = line3d.ToLine2d();

7.3 三维圆弧(LcArc3d)

7.3.1 数据结构

三维圆弧需要额外的方向信息来确定其在空间中的位置:

public class LcArc3d : LcEntity, IUpdateObject
{
    /// <summary>
    /// 圆弧中心(三维坐标)
    /// </summary>
    public Point3d Center { get; set; }

    /// <summary>
    /// 半径
    /// </summary>
    public double Radius { get; set; }

    /// <summary>
    /// 圆弧所在平面的法向量
    /// </summary>
    public Vector3d Normal { get; set; } = Vector3d.ZAxis;

    /// <summary>
    /// 起始角度
    /// </summary>
    public double StartAngle { get; set; }

    /// <summary>
    /// 终止角度
    /// </summary>
    public double EndAngle { get; set; }

    /// <summary>
    /// X轴方向(定义角度参考方向)
    /// </summary>
    public Vector3d XDirection { get; set; } = Vector3d.XAxis;

    public override string TypeName => "Arc3d";

    /// <summary>
    /// 获取圆弧所在的平面
    /// </summary>
    public Plane GetPlane()
    {
        return new Plane(Center, Normal);
    }

    /// <summary>
    /// 获取三维起点
    /// </summary>
    public Point3d StartPoint3d
    {
        get
        {
            var yDir = Normal.Cross(XDirection).Normalize();
            return new Point3d(
                Center.X + Radius * (Math.Cos(StartAngle) * XDirection.X +
                    Math.Sin(StartAngle) * yDir.X),
                Center.Y + Radius * (Math.Cos(StartAngle) * XDirection.Y +
                    Math.Sin(StartAngle) * yDir.Y),
                Center.Z + Radius * (Math.Cos(StartAngle) * XDirection.Z +
                    Math.Sin(StartAngle) * yDir.Z)
            );
        }
    }

    /// <summary>
    /// 离散化为三维点序列
    /// </summary>
    public List<Point3d> Tessellate(int segments = 32)
    {
        var points = new List<Point3d>();
        var yDir = Normal.Cross(XDirection).Normalize();
        var sweep = EndAngle - StartAngle;
        if (sweep < 0) sweep += 2 * Math.PI;

        for (int i = 0; i <= segments; i++)
        {
            var t = (double)i / segments;
            var angle = StartAngle + sweep * t;
            var cos = Math.Cos(angle);
            var sin = Math.Sin(angle);

            points.Add(new Point3d(
                Center.X + Radius * (cos * XDirection.X + sin * yDir.X),
                Center.Y + Radius * (cos * XDirection.Y + sin * yDir.Y),
                Center.Z + Radius * (cos * XDirection.Z + sin * yDir.Z)
            ));
        }

        return points;
    }
}

7.4 三维圆(LcCircle3d)

7.4.1 数据结构

public class LcCircle3d : LcEntity, IUpdateObject
{
    /// <summary>
    /// 圆心(三维坐标)
    /// </summary>
    public Point3d Center { get; set; }

    /// <summary>
    /// 半径
    /// </summary>
    public double Radius { get; set; }

    /// <summary>
    /// 法向量(圆所在平面的法线)
    /// </summary>
    public Vector3d Normal { get; set; } = Vector3d.ZAxis;

    /// <summary>
    /// 周长
    /// </summary>
    public double Circumference => 2 * Math.PI * Radius;

    /// <summary>
    /// 面积
    /// </summary>
    public double Area => Math.PI * Radius * Radius;

    public override string TypeName => "Circle3d";

    /// <summary>
    /// 获取圆上指定角度的三维点
    /// </summary>
    public Point3d PointAt(double angle)
    {
        // 构建局部坐标系
        var xDir = GetLocalXDirection();
        var yDir = Normal.Cross(xDir).Normalize();

        return new Point3d(
            Center.X + Radius * (Math.Cos(angle) * xDir.X +
                Math.Sin(angle) * yDir.X),
            Center.Y + Radius * (Math.Cos(angle) * xDir.Y +
                Math.Sin(angle) * yDir.Y),
            Center.Z + Radius * (Math.Cos(angle) * xDir.Z +
                Math.Sin(angle) * yDir.Z)
        );
    }

    /// <summary>
    /// 构建局部X方向
    /// </summary>
    private Vector3d GetLocalXDirection()
    {
        // 选择一个与法向量不共线的向量
        var reference = Math.Abs(Normal.Dot(Vector3d.ZAxis)) < 0.9
            ? Vector3d.ZAxis : Vector3d.XAxis;
        return reference.Cross(Normal).Normalize();
    }

    /// <summary>
    /// 离散化为三维点序列
    /// </summary>
    public List<Point3d> Tessellate(int segments = 64)
    {
        var points = new List<Point3d>();
        for (int i = 0; i <= segments; i++)
        {
            var angle = 2 * Math.PI * i / segments;
            points.Add(PointAt(angle));
        }
        return points;
    }
}

7.5 工作平面(LcWorkPlane3d)

7.5.1 概念说明

工作平面是LightCAD三维建模中的重要概念。它定义了一个局部坐标系,允许用户在任意方向的平面上进行二维绘图操作,然后将结果映射到三维空间中。

7.5.2 数据结构

public class LcWorkPlane3d : LcEntity, IUpdateObject
{
    /// <summary>
    /// 工作平面原点
    /// </summary>
    public Point3d Origin { get; set; }

    /// <summary>
    /// 平面法向量
    /// </summary>
    public Vector3d Normal { get; set; } = Vector3d.ZAxis;

    /// <summary>
    /// 局部X轴方向
    /// </summary>
    public Vector3d XAxis { get; set; } = Vector3d.XAxis;

    /// <summary>
    /// 局部Y轴方向(自动计算)
    /// </summary>
    public Vector3d YAxis => Normal.Cross(XAxis).Normalize();

    /// <summary>
    /// 显示大小(工作平面网格的范围)
    /// </summary>
    public double DisplaySize { get; set; } = 1000;

    /// <summary>
    /// 网格间距
    /// </summary>
    public double GridSpacing { get; set; } = 10;

    /// <summary>
    /// 是否显示网格
    /// </summary>
    public bool ShowGrid { get; set; } = true;

    public override string TypeName => "WorkPlane3d";

    /// <summary>
    /// 将局部二维坐标转换为世界三维坐标
    /// </summary>
    public Point3d LocalToWorld(Point2d localPoint)
    {
        return new Point3d(
            Origin.X + localPoint.X * XAxis.X + localPoint.Y * YAxis.X,
            Origin.Y + localPoint.X * XAxis.Y + localPoint.Y * YAxis.Y,
            Origin.Z + localPoint.X * XAxis.Z + localPoint.Y * YAxis.Z
        );
    }

    /// <summary>
    /// 将世界三维坐标转换为局部二维坐标
    /// </summary>
    public Point2d WorldToLocal(Point3d worldPoint)
    {
        var v = new Vector3d(
            worldPoint.X - Origin.X,
            worldPoint.Y - Origin.Y,
            worldPoint.Z - Origin.Z
        );

        return new Point2d(
            v.Dot(XAxis),
            v.Dot(YAxis)
        );
    }

    /// <summary>
    /// 将三维点投影到工作平面上
    /// </summary>
    public Point3d ProjectPoint(Point3d point)
    {
        var local = WorldToLocal(point);
        return LocalToWorld(local);
    }

    /// <summary>
    /// 获取变换矩阵(局部到世界)
    /// </summary>
    public Matrix4d GetTransformMatrix()
    {
        return new Matrix4d(
            XAxis.X, YAxis.X, Normal.X, Origin.X,
            XAxis.Y, YAxis.Y, Normal.Y, Origin.Y,
            XAxis.Z, YAxis.Z, Normal.Z, Origin.Z,
            0, 0, 0, 1
        );
    }
}

7.5.3 使用示例

// 创建一个倾斜45度的工作平面
var workPlane = new LcWorkPlane3d
{
    Origin = new Point3d(0, 0, 100),
    Normal = new Vector3d(0, -Math.Sin(Math.PI / 4), Math.Cos(Math.PI / 4)),
    XAxis = Vector3d.XAxis,
    GridSpacing = 10,
    ShowGrid = true
};

// 在工作平面上创建一个矩形
var p1 = workPlane.LocalToWorld(new Point2d(0, 0));
var p2 = workPlane.LocalToWorld(new Point2d(100, 0));
var p3 = workPlane.LocalToWorld(new Point2d(100, 50));
var p4 = workPlane.LocalToWorld(new Point2d(0, 50));

var rect = new LcPolyline();
rect.AddVertex(new Point2d(p1.X, p1.Y));
rect.AddVertex(new Point2d(p2.X, p2.Y));
rect.AddVertex(new Point2d(p3.X, p3.Y));
rect.AddVertex(new Point2d(p4.X, p4.Y));
rect.IsClosed = true;

7.6 三维组(LcGroup3)

7.6.1 数据结构

LcGroup3实现了组合模式(Composite Pattern),将多个三维实体组织为一个逻辑单元:

public class LcGroup3 : LcEntity, IUpdateObject
{
    /// <summary>
    /// 子实体集合
    /// </summary>
    public List<LcEntity> Children { get; set; } = new();

    /// <summary>
    /// 组的变换矩阵
    /// </summary>
    public Matrix4d Transform { get; set; } = Matrix4d.Identity;

    /// <summary>
    /// 组名称
    /// </summary>
    public string GroupName { get; set; }

    public override string TypeName => "Group3";

    /// <summary>
    /// 添加子实体
    /// </summary>
    public void Add(LcEntity entity)
    {
        Children.Add(entity);
    }

    /// <summary>
    /// 移除子实体
    /// </summary>
    public bool Remove(LcEntity entity)
    {
        return Children.Remove(entity);
    }

    /// <summary>
    /// 将组展开为独立实体
    /// </summary>
    public List<LcEntity> Explode()
    {
        var result = new List<LcEntity>();
        foreach (var child in Children)
        {
            var clone = child.Clone();
            clone.TransformBy(Transform);
            result.Add(clone);
        }
        return result;
    }

    public override void TransformBy(Matrix4d matrix)
    {
        Transform = matrix * Transform;
    }

    public override BoundingBox2d Bounds
    {
        get
        {
            if (Children.Count == 0)
                return new BoundingBox2d();

            var bounds = Children[0].Bounds;
            for (int i = 1; i < Children.Count; i++)
            {
                bounds = bounds.Union(Children[i].Bounds);
            }
            return bounds;
        }
    }
}

7.7 三维阵列(LcArray3)

7.7.1 数据结构

LcArray3支持在三维空间中创建实体的参数化阵列复制:

public class LcArray3 : LcEntity, IUpdateObject
{
    /// <summary>
    /// 源实体
    /// </summary>
    public LcEntity SourceEntity { get; set; }

    /// <summary>
    /// 阵列类型
    /// </summary>
    public ArrayType Type { get; set; }

    /// <summary>
    /// X方向数量
    /// </summary>
    public int CountX { get; set; } = 1;

    /// <summary>
    /// Y方向数量
    /// </summary>
    public int CountY { get; set; } = 1;

    /// <summary>
    /// Z方向数量
    /// </summary>
    public int CountZ { get; set; } = 1;

    /// <summary>
    /// X方向间距
    /// </summary>
    public double SpacingX { get; set; }

    /// <summary>
    /// Y方向间距
    /// </summary>
    public double SpacingY { get; set; }

    /// <summary>
    /// Z方向间距
    /// </summary>
    public double SpacingZ { get; set; }

    /// <summary>
    /// 环形阵列中心
    /// </summary>
    public Point3d PolarCenter { get; set; }

    /// <summary>
    /// 环形阵列轴向量
    /// </summary>
    public Vector3d PolarAxis { get; set; } = Vector3d.ZAxis;

    /// <summary>
    /// 环形阵列总角度
    /// </summary>
    public double PolarAngle { get; set; } = 2 * Math.PI;

    /// <summary>
    /// 环形阵列数量
    /// </summary>
    public int PolarCount { get; set; }

    public override string TypeName => "Array3";

    /// <summary>
    /// 生成所有阵列实例
    /// </summary>
    public List<LcEntity> GenerateInstances()
    {
        return Type switch
        {
            ArrayType.Rectangular => GenerateRectangular(),
            ArrayType.Polar => GeneratePolar(),
            _ => new List<LcEntity>()
        };
    }

    private List<LcEntity> GenerateRectangular()
    {
        var instances = new List<LcEntity>();
        for (int ix = 0; ix < CountX; ix++)
        {
            for (int iy = 0; iy < CountY; iy++)
            {
                for (int iz = 0; iz < CountZ; iz++)
                {
                    if (ix == 0 && iy == 0 && iz == 0) continue;

                    var clone = SourceEntity.Clone();
                    var translation = Matrix4d.CreateTranslation(
                        ix * SpacingX,
                        iy * SpacingY,
                        iz * SpacingZ
                    );
                    clone.TransformBy(translation);
                    instances.Add(clone);
                }
            }
        }
        return instances;
    }

    private List<LcEntity> GeneratePolar()
    {
        var instances = new List<LcEntity>();
        var angleStep = PolarAngle / PolarCount;

        for (int i = 1; i < PolarCount; i++)
        {
            var clone = SourceEntity.Clone();
            var angle = angleStep * i;

            // 绕指定轴旋转
            var toOrigin = Matrix4d.CreateTranslation(
                -PolarCenter.X, -PolarCenter.Y, -PolarCenter.Z);
            var rotation = CreateRotationAroundAxis(PolarAxis, angle);
            var backToPos = Matrix4d.CreateTranslation(
                PolarCenter.X, PolarCenter.Y, PolarCenter.Z);

            clone.TransformBy(backToPos * rotation * toOrigin);
            instances.Add(clone);
        }
        return instances;
    }
}

public enum ArrayType
{
    Rectangular,  // 矩形阵列
    Polar         // 环形阵列
}

7.8 三维轮廓(LcProfile3d)

7.8.1 数据结构

LcProfile3d用于定义三维空间中的封闭轮廓,常用作拉伸、旋转等实体建模操作的截面:

public class LcProfile3d : LcEntity, IUpdateObject
{
    /// <summary>
    /// 轮廓所在的工作平面
    /// </summary>
    public LcWorkPlane3d WorkPlane { get; set; }

    /// <summary>
    /// 外轮廓曲线(必须闭合)
    /// </summary>
    public LcPolyline OuterLoop { get; set; }

    /// <summary>
    /// 内部孔洞轮廓(可选)
    /// </summary>
    public List<LcPolyline> InnerLoops { get; set; } = new();

    /// <summary>
    /// 轮廓面积(扣除孔洞)
    /// </summary>
    public double Area
    {
        get
        {
            var outerArea = OuterLoop.Area;
            var innerArea = InnerLoops.Sum(loop => loop.Area);
            return outerArea - innerArea;
        }
    }

    public override string TypeName => "Profile3d";

    /// <summary>
    /// 获取轮廓的三维点序列
    /// </summary>
    public List<Point3d> GetWorldPoints()
    {
        var points2d = OuterLoop.Tessellate();
        return points2d.Select(p => WorkPlane.LocalToWorld(p)).ToList();
    }

    /// <summary>
    /// 验证轮廓是否有效
    /// </summary>
    public bool IsValid()
    {
        if (OuterLoop == null || !OuterLoop.IsClosed) return false;
        if (OuterLoop.VertexCount < 3) return false;

        // 检查内部轮廓是否都在外部轮廓内
        foreach (var inner in InnerLoops)
        {
            if (!inner.IsClosed) return false;
            foreach (var vertex in inner.Vertices)
            {
                var polygon = OuterLoop.Vertices
                    .Select(v => v.Position).ToList();
                if (!GeometryUtils.PointInPolygon(vertex.Position, polygon))
                    return false;
            }
        }

        return true;
    }
}

7.9 容器引用(LcContianerRef3)

7.9.1 概念说明

LcContianerRef3是LightCAD中实现组件实例化和引用的机制。类似于AutoCAD中的块引用(Block Reference),它允许在文档中多次放置同一个组件定义的实例,而不必复制所有数据。

7.9.2 数据结构

public class LcContianerRef3 : LcEntity, IUpdateObject
{
    /// <summary>
    /// 引用的组件定义标识
    /// </summary>
    public LcGuid ComponentGuid { get; set; }

    /// <summary>
    /// 插入点(在世界坐标中的位置)
    /// </summary>
    public Point3d InsertionPoint { get; set; }

    /// <summary>
    /// 旋转角度
    /// </summary>
    public double Rotation { get; set; }

    /// <summary>
    /// 缩放因子
    /// </summary>
    public Vector3d Scale { get; set; } = new Vector3d(1, 1, 1);

    /// <summary>
    /// 完整的变换矩阵
    /// </summary>
    public Matrix4d InsertionMatrix
    {
        get
        {
            var scale = Matrix4d.CreateScale(Scale.X, Scale.Y, Scale.Z);
            var rotation = Matrix4d.CreateRotationZ(Rotation);
            var translation = Matrix4d.CreateTranslation(
                InsertionPoint.X, InsertionPoint.Y, InsertionPoint.Z);
            return translation * rotation * scale;
        }
    }

    /// <summary>
    /// 实例属性覆盖
    /// </summary>
    public Dictionary<string, object> PropertyOverrides { get; set; } = new();

    public override string TypeName => "ContainerRef3";

    /// <summary>
    /// 获取引用的组件定义
    /// </summary>
    public LcGroup3 GetDefinition()
    {
        // 从文档的块定义集合中查找
        return Document?.Blocks?.Find(ComponentGuid);
    }

    /// <summary>
    /// 展开引用为独立实体
    /// </summary>
    public List<LcEntity> Explode()
    {
        var definition = GetDefinition();
        if (definition == null) return new List<LcEntity>();

        var result = new List<LcEntity>();
        foreach (var child in definition.Children)
        {
            var clone = child.Clone();
            clone.TransformBy(InsertionMatrix);
            result.Add(clone);
        }
        return result;
    }
}

7.10 三维图元的坐标变换

7.10.1 世界坐标与局部坐标

在三维建模中,坐标变换是核心操作。LightCAD中的三维实体需要在不同坐标系之间转换:

// 世界坐标系(WCS)
// 全局固定的笛卡尔坐标系

// 用户坐标系(UCS)
// 用户自定义的坐标系,通过工作平面定义

// 对象坐标系(OCS)
// 实体自身的局部坐标系

// WCS → OCS 变换
public Point3d WorldToObject(Point3d worldPoint, Matrix4d objectTransform)
{
    var inverseTransform = objectTransform.Inverse();
    return inverseTransform.Transform(worldPoint);
}

// OCS → WCS 变换
public Point3d ObjectToWorld(Point3d objectPoint, Matrix4d objectTransform)
{
    return objectTransform.Transform(objectPoint);
}

7.10.2 常用三维变换

// 绕任意轴旋转
public static Matrix4d RotateAroundAxis(Point3d point, Vector3d axis, double angle)
{
    var toOrigin = Matrix4d.CreateTranslation(-point.X, -point.Y, -point.Z);
    var backToPos = Matrix4d.CreateTranslation(point.X, point.Y, point.Z);

    var n = axis.Normalize();
    var cos = Math.Cos(angle);
    var sin = Math.Sin(angle);
    var t = 1 - cos;

    var rotation = new Matrix4d(
        t * n.X * n.X + cos,       t * n.X * n.Y - sin * n.Z, t * n.X * n.Z + sin * n.Y, 0,
        t * n.X * n.Y + sin * n.Z, t * n.Y * n.Y + cos,       t * n.Y * n.Z - sin * n.X, 0,
        t * n.X * n.Z - sin * n.Y, t * n.Y * n.Z + sin * n.X, t * n.Z * n.Z + cos,       0,
        0,                          0,                          0,                          1
    );

    return backToPos * rotation * toOrigin;
}

// 三维镜像(关于平面镜像)
public static Matrix4d MirrorAboutPlane(Plane plane)
{
    var n = plane.Normal.Normalize();
    var d = -n.Dot(new Vector3d(
        plane.Origin.X, plane.Origin.Y, plane.Origin.Z));

    return new Matrix4d(
        1 - 2 * n.X * n.X, -2 * n.X * n.Y,     -2 * n.X * n.Z,     -2 * n.X * d,
        -2 * n.X * n.Y,     1 - 2 * n.Y * n.Y,  -2 * n.Y * n.Z,     -2 * n.Y * d,
        -2 * n.X * n.Z,     -2 * n.Y * n.Z,      1 - 2 * n.Z * n.Z,  -2 * n.Z * d,
        0,                   0,                    0,                    1
    );
}

7.11 本章小结

本章详细介绍了LightCAD的三维图元系统。三维图元在二维图元的基础上增加了Z坐标和空间方位信息,能够表示任意空间位置和方向的几何实体。工作平面(LcWorkPlane3d)提供了在任意方向的平面上进行绘图的能力,三维组(LcGroup3)和阵列(LcArray3)实现了实体的组织和批量复制,容器引用(LcContianerRef3)提供了高效的组件实例化机制。这些三维图元为后续的实体建模和视图构建奠定了基础。


上一章第六章:二维图元系统

下一章第八章:实体建模系统