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;
}