不等比缩放

2025年3月23日22:48:49

public  class 矩阵

{
    [CommandMethod("xx")]
    public void 选择curve并不等比缩放()
    {
        double scaleX = 0.5, scaleY = 3;// X轴缩放因子,Y轴缩放因子
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;
        //db.EraseAll();
        //选择曲线
        var curve = db.GetEntity("选择曲线") as Curve;
        if (curve == null ||curve.IsErased) return;
        //Ifox封装的curve曲线不等比缩放函数
        // 提示用户选择一个点
        PromptPointOptions ppo = new PromptPointOptions("\n请选择一个点: ");
        PromptPointResult ppr = ed.GetPoint(ppo);

        // 检查用户是否成功选择了一个点
        if (ppr.Status != PromptStatus.OK) return;
        Point3d selectedPoint = ppr.Value;
        // 这里可以对选择的点进行进一步处理
        ed.WriteMessage("\n你选择的点坐标是: ({0}, {1}, {2})", selectedPoint.X, selectedPoint.Y, selectedPoint.Z);
        var scaleCurve = curve.GetScaleCurve1(selectedPoint, scaleX, scaleY);
        scaleCurve.ColorIndex = 1;
        db.AddEntityToModeSpace(scaleCurve);
    }
    [CommandMethod("tt")]

    public void 随机生成不等比缩放点转线()
    {
        double scaleX = 1.5, scaleY = 4, scaleZ = 2;// X轴缩放因子,Y轴缩放因子
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;
        db.EraseAll();
        // 原始点集合
        List<Point3d> originalPoints = new List<Point3d>
        {
            new Point3d(-10, -10, 10),
            new Point3d(-30, -10, 10),
            new Point3d(-20, -30, 10)
        };
        Random random = new Random();
        //加入随机点
        for (int i = 0; i < 3; i++)
        {
            double x = Math.Round(random.NextDouble() * 20 + 10, 3);
            double y = Math.Round(random.NextDouble() * 40 + 10, 3);
            double z = Math.Round(random.NextDouble() * 10 + 10, 3);

            Point3d point = new Point3d(x, y, z);
            originalPoints.Add(point);
        }
        ed.WriteMessage($"\n原始点:\n");
        //point3d转dbpoint封装函数
        List<DBPoint> originalDbPoints = Convertex.Point3d2Dbpoint(originalPoints, 0);
        db.AddEntityToModeSpace(originalDbPoints.ToArray());
        db.AddEntityToModeSpace(originalPoints.ToPolyline(0, 0, true));
        originalPoints.ForEach(p => ed.WriteMessage($"({p.X},{p.Y},{p.Z}) "));
        //point3d转线封装函数
        var curve = originalPoints.ToPolyline(3, 0, true) as Curve;
        //Ifox封装的curve曲线不等比缩放函数
        var scaleCurve = curve.GetScaleCurve(curve.GeometricExtents.MinPoint, 20, 5);
        db.AddEntityToModeSpace(scaleCurve);
        // 缩放点
        List<Point3d> scaledPoints = ScalePoints(originalPoints, scaleX, scaleY, scaleZ);
        ed.WriteMessage("\n缩放后:\n");
        //point3d转dbpoint封装函数
        List<DBPoint> scaleddbPoints = Convertex.Point3d2Dbpoint(scaledPoints, 1);
        scaledPoints.ForEach(p => ed.WriteMessage($"({p.X},{p.Y},{p.Z}) "));
        //点和线加入模型空间
        db.AddEntityToModeSpace(scaleddbPoints.ToArray());
        db.AddEntityToModeSpace(scaledPoints.ToPolyline(1, 0.03, true));

    }
    public List<Point3d> ScalePoints(List<Point3d> points, Point3d basePoint, double scaleX, double scaleY,double scaleZ)
    {
        return points
            .Select(p => ScaleSinglePoint(p, basePoint, scaleX, scaleY,scaleZ))
            .ToList();
    }

    /// <summary>
    /// 自动确定左下角基准点的重载版本
    /// </summary>
    public List<Point3d> ScalePoints(List<Point3d> points, double scaleX, double scaleY,double scaleZ)
    {
        Point3d basePoint = FindBasePoint(points);
        return ScalePoints(points, basePoint, scaleX, scaleY,scaleZ);
    }

    /// <summary>
    /// 单点缩放计算方法
    /// </summary>
    private Point3d ScaleSinglePoint(Point3d point, Point3d basePoint, double scaleX, double scaleY, double scaleZ)
    {
        return new Point3d(
            basePoint.X + (point.X - basePoint.X) * scaleX,
            basePoint.Y + (point.Y - basePoint.Y) * scaleY,
            basePoint.Z + (point.Z - basePoint.Z) * scaleZ
        );
    }

    /// <summary>
    /// 自动查找左下角基准点(X最小,Y最小)
    /// </summary>
    private Point3d FindBasePoint(List<Point3d> points)
    {
        return points
            .OrderBy(p => p.X)
            .ThenBy(p => p.Y)
            .FirstOrDefault();
    }
    
}
public static class 矩阵base
{
    public static Curve GetScaleCurve1(this Curve cur, Point3d pt, double x, double y)
    {
        // 先做个z平面
        // 使用基点 pt 和 Z 轴向量创建一个平面 zPlane,后续的投影操作将基于这个平面进行
        using var zPlane = new Plane(pt, Vector3d.ZAxis);

        // 克隆一个,防止修改到原来的
        // 克隆输入的曲线 cur,得到一个新的曲线 cur2,避免对原始曲线进行修改
        using var cur2 = cur.CloneEx();

        // 因为旋转投影后只能比原来小,所以遇到先放大
        // 循环条件:当 x 或 y 的绝对值大于 1 时,说明需要进行放大操作
        while (Math.Abs(x) > 1 || Math.Abs(y) > 1)
        {
            // 对曲线 cur2 进行缩放操作,缩放比例为 2,基点为 pt
            cur2.TransformBy(Matrix3d.Scaling(2, pt));
            // 将 x 和 y 分别除以 2,更新缩放比例
            x /= 2;
            y /= 2;
        }

        // 旋转投影
        // 计算 x 方向的旋转角度 xA,使用反余弦函数得到弧度值
        var xA = Math.Acos(x);
        // 对曲线 cur2 进行绕 Y 轴旋转操作,旋转角度为 xA,基点为 pt
        cur2.TransformBy(Matrix3d.Rotation(xA, Vector3d.YAxis, pt));

        // 将旋转后的曲线 cur2 投影到 zPlane 平面上,得到新的曲线 cur3
        using var cur3 = cur2.GetOrthoProjectedCurve(zPlane);

        // 再次旋转投影
        // 计算 y 方向的旋转角度 yA,使用反余弦函数得到弧度值
        var yA = Math.Acos(y);
        // 对曲线 cur3 进行绕 X 轴旋转操作,旋转角度为 yA,基点为 pt
        cur3.TransformBy(Matrix3d.Rotation(yA, Vector3d.XAxis, pt));
        // 将再次旋转后的曲线 cur3 投影到 zPlane 平面上,得到最终的曲线 cur4
        var cur4 = cur3.GetOrthoProjectedCurve(zPlane);

        // 设置属性
        // 将原始曲线 cur 的属性复制到最终曲线 cur4 上,保证曲线属性一致
        cur4.SetPropertiesFrom(cur);
        // 返回最终的转换后的曲线 cur4
        return cur4;
    }
}


ifox的缩放封装

public static Curve GetScaleCurve(this Curve cur, Point3d pt, double x, double y)
{
    // 创建基准平面(XY平面)
    using var zPlane = new Plane(pt, Vector3d.ZAxis); 

    // 克隆原始曲线(保留原始数据)
    using var cur2 = cur.CloneEx();

    // 错误1:缩放因子分解逻辑
    while (Math.Abs(x) > 1 || Math.Abs(y) > 1)
    {
        cur2.TransformBy(Matrix3d.Scaling(2, pt));
        x /= 2;
        y /= 2;
    }
    /* 
    错误分析:
    1. 强行将缩放因子分解为2的幂次方
    2. 实际缩放因子累计为 2^n,与输入的x/y无关
    3. 完全破坏原始缩放比例关系
    */

    // 错误2:错误使用反余弦函数
    var xA = Math.Acos(x); // 当|x|>1时抛出异常
    cur2.TransformBy(Matrix3d.Rotation(xA, Vector3d.YAxis, pt));

    /* 
    错误分析:
    1. acos(x)要求x∈[-1,1],但x是缩放因子
    2. 旋转角度与缩放因子无数学对应关系
    3. Y轴旋转实际改变的是Z-X平面方向
    */

    // 投影到XY平面(丢失Z坐标信息)
    using var cur3 = cur2.GetOrthoProjectedCurve(zPlane);

    // 重复Y轴方向的错误处理
    var yA = Math.Acos(y); // 同样存在参数范围问题
    cur3.TransformBy(Matrix3d.Rotation(yA, Vector3d.XAxis, pt));
    var cur4 = cur3.GetOrthoProjectedCurve(zPlane);

    // 复制属性(仅保留线条样式)
    cur4.SetPropertiesFrom(cur);
    return cur4;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山水CAD插件定制

你的鼓励是我创作最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值