public class Point
{
public Point() { }
public Point(double xx, double yy, double zz)
{
X = xx;
Y = yy;
Z = zz;
}
bool euqal(Point other) {
bool isEqual = false;
if (Math.Sqrt(Math.Pow(other.X-X,2) + Math.Pow(other.Y-Y,2) + Math.Pow(other.Z-Z,2))<1.0)
{
isEqual = true;
}
return isEqual;
}
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}
//去除粗差
public class RemoveOutlier
{
//static void Main(string[] args)
//{
// List values = new List
// {
// 10.5, 12.3, 9.8, 53.5, 8.6, 11.2, 8.9, 12.1, 10.2, 11.6, 10.7, 9.5
// };
// List cleanValues = RemoveOutliers(values);
// Console.WriteLine("Original values: " + string.Join(",", values));
// Console.WriteLine("Clean values: " + string.Join(",", cleanValues));
// Console.ReadLine();
//}
public static List RemoveOutliers(List datas,double score)
{
List cleanData = new List();
List data = new List();
foreach (Point3d ii in datas) {
data.Add(ii.Z);
}
double mean = data.Average();
double stdev = CalculateStandardDeviation(data, mean);
for (int i=0;i data, double mean)
{
double sumOfSquaredDifferences = 0;
foreach (double value in data)
{
sumOfSquaredDifferences += Math.Pow(value - mean, 2);
}
double variance = sumOfSquaredDifferences / (data.Count - 1);
double stdev = Math.Sqrt(variance);
return stdev;
}
}
public class Interpolate
{
//static void Main(string[] args)
//{
// //已知点
// // Known points with x, y, and z values
// List points = new List
// {
// new Point { X = 0, Y = 0, Z = 0 },
// new Point { X = 1, Y = 1, Z = 1 },
// new Point { X = 2, Y = 2, Z = 4 },
// new Point { X = 3, Y = 3, Z = 9 }
// };
// //查找点
// double x = 1.5; // X coordinate of the point
// double y = 1.5; // Y coordinate of the point
// // Perform quadratic interpolation
// //二次插值函数
// double zQuadratic = QuadraticInterpolation(points, x, y);
// Console.WriteLine("Z value of point ({0}, {1}) using quadratic interpolation: {2}", x, y, zQuadratic);
// //三次插值函数
// // Perform cubic interpolation
// double zCubic = CubicInterpolation(points, x, y);
// Console.WriteLine("Z value of point ({0}, {1}) using cubic interpolation: {2}", x, y, zCubic);
// Console.ReadLine();
//}
public Interpolate() { }
public static double QuadraticInterpolation(List points, double x, double y)
{
double z = 0;
// Find the three nearest points
Point[] closestPoints = GetClosestPoints(points, x, y, 3);
if (points[0].Equals(points[1]) || points[0].Equals(points[2]) || points[1].Equals(points[2]))
{
z = (points[0].Z + points[1].Z + points[2].Z) / 3;
return z;
}
// Calculate coefficients for the quadratic polynomial
double[,] a = new double[3, 3];
double[] b = new double[3];
for (int i = 0; i < 3; i++)
{
a[i, 0] = 1;
a[i, 1] = closestPoints[i].X;
a[i, 2] = closestPoints[i].Y;
b[i] = closestPoints[i].Z;
}
double[,] aInverse = InverseMatrix(a);
double[] c = MultiplyMatrixVector(aInverse, b);
// Calculate the z value of the point using the quadratic polynomial
z = c[0] + c[1] * x + c[2] * y;
return z;
}
public static double CubicInterpolation(List points, double x, double y)
{
double z = 0;
// Find the four nearest points
Point[] closestPoints = GetClosestPoints(points, x, y, 4);
// Calculate coefficients for the cubic polynomial
double[,] a = new double[4, 4];
double[] b = new double[4];
for (int i = 0; i < 4; i++)
{
a[i, 0] = 1;
a[i, 1] = closestPoints[i].X;
a[i, 2] = closestPoints[i].Y;
a[i, 3] = closestPoints[i].X * closestPoints[i].Y;
b[i] = closestPoints[i].Z;
}
double[,] aInverse = InverseMatrix(a);
double[] c = MultiplyMatrixVector(aInverse, b);
// Calculate the z value of the point using the cubic polynomial
z = c[0] + c[1] * x + c[2] * y + c[3] * x * y;
return z;
}
static Point[] GetClosestPoints(List points, double x, double y, int numberOfPoints)
{
// Sort the points by distance
//Point[] sortedPoints = points.OrderBy(p => Math.Sqrt(Math.Pow(p.X - x, 2) + Math.Pow(p.Y - y, 2))).ToArray();
SortedDictionary dict = new SortedDictionary();
for (int i = 0; i < points.Count(); ++i)
{
Point p = points[i];
double dist = Math.Sqrt(Math.Pow(p.X - x, 2) + Math.Pow(p.Y - y, 2));
dict.Add(dist, p);
}
Point[] pts = new Point[numberOfPoints];
int index = 0;
foreach (KeyValuePair kvp in dict)
{
//Console.WriteLine("Key: {0}, Value: {1}", kvp.Key, kvp.Value);
pts[index] = kvp.Value;
index++;
if (index >= numberOfPoints) break;
}
return pts;
}
static double[,] InverseMatrix(double[,] a)
{
int n = Convert.ToInt32(Math.Sqrt(a.Length));
double[,] inv = new double[n, n];
double det = Determinant(a);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
double[,] minor = Minor(a, i, j);
inv[j, i] = Math.Pow(-1, i + j) * Determinant(minor) / det;
}
}
return inv;
}
static double Determinant(double[,] a)
{
int n = Convert.ToInt32(Math.Sqrt(a.Length));
double det = 0;
if (n == 1)
{
det = a[0, 0];
}
else if (n == 2)
{
det = a[0, 0] * a[1, 1] - a[0, 1] * a[1, 0];
}
else
{
for (int i = 0; i < n; i++)
{
double[,] minor = Minor(a, 0, i);
det += Math.Pow(-1, i) * a[0, i] * Determinant(minor);
}
}
return det;
}
static double[,] Minor(double[,] a, int i, int j)
{
int n = Convert.ToInt32(Math.Sqrt(a.Length));
double[,] minor = new double[n - 1, n - 1];
for (int k = 0; k < n; k++)
{
for (int l = 0; l < n; l++)
{
if (k != i && l != j)
{
int p = k < i ? k : k - 1;
int q = l < j ? l : l - 1;
minor[p, q] = a[k, l];
}
}
}
return minor;
}
static double[] MultiplyMatrixVector(double[,] a, double[] b)
{
int m = a.GetLength(0);
int n = a.GetLength(1);
double[] c = new double[m];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
c[i] += a[i, j] * b[j];
}
}
return c;
}
}
class KdTreeNode
{
public Point3d Point { get; set; }
public KdTreeNode Left { get; set; }
public KdTreeNode Right { get; set; }
public KdTreeNode(Point3d point)
{
Point = point;
Left = null;
Right = null;
}
}
// kd树类
class KdTree
{
private KdTreeNode root;
private List m_points;
public KdTree(List points)
{
root = BuildKdTree(points, 0);
m_points = points;
}
// 构建kd树
private KdTreeNode BuildKdTree(List points, int depth)
{
if (points.Count == 0)
{
return null;
}
int axis = depth % 2;
points.Sort((a, b) => axis == 0 ? a.X.CompareTo(b.X) : a.Y.CompareTo(b.Y));
int medianIndex = points.Count / 2;
Point3d medianPoint = points[medianIndex];
KdTreeNode node = new KdTreeNode(medianPoint);
node.Left = BuildKdTree(points.GetRange(0, medianIndex), depth + 1);
node.Right = BuildKdTree(points.GetRange(medianIndex + 1, points.Count - medianIndex - 1), depth + 1);
return node;
}
// 最近邻搜索
public Point3d FindNearestNeighbor(Point3d target)
{
Point3d pt = new Point3d(0.0, 0.0, 0.0);
if (0 == m_points.Count()) return pt;
pt = m_points[0];
if (1 == m_points.Count()) return pt;
for (int i = 1; i < m_points.Count(); ++i)
{
Point3d ptF = m_points[i];
double dist = Distance(target, ptF);
double distOld = Distance(target, pt);
if (dist < distOld) pt = ptF;
}
return pt;
//KdTreeNode nearestNode = FindNearestNeighbor(root, target, 0);
//return nearestNode.Point;
}
private KdTreeNode FindNearestNeighbor(KdTreeNode node, Point3d target, int depth)
{
if (node == null)
return null;
int k = 3;
int axis = depth % k;
KdTreeNode nearestNode;
KdTreeNode branchNode;
if (target[axis] < node.Point[axis])
{
nearestNode = FindNearestNeighbor(node.Left, target, depth + 1);
branchNode = node.Right;
}
else
{
nearestNode = FindNearestNeighbor(node.Right, target, depth + 1);
branchNode = node.Left;
}
if (nearestNode == null || Distance(target, nearestNode.Point) > Distance(target, node.Point))
nearestNode = node;
if (Distance(target, nearestNode.Point) > Math.Abs(target[axis] - node.Point[axis]))
{
KdTreeNode otherBranchNode = (branchNode == node.Left) ? node.Right : node.Left;
KdTreeNode potentialNode = FindNearestNeighbor(otherBranchNode, target, depth + 1);
if (potentialNode != null && Distance(target, nearestNode.Point) > Distance(target, potentialNode.Point))
nearestNode = potentialNode;
}
return nearestNode;
}
// 计算两个点之间的欧几里得距离
public double Distance(Point3d p1, Point3d p2)
{
double dx = p1.X - p2.X;
double dy = p1.Y - p2.Y;
return Math.Sqrt(dx * dx + dy * dy);
}
}
public class ReadFile
{
public static List readFilePts(string path)
{
List points = new List();
string filePath = path;
try
{
using (StreamReader reader = new StreamReader(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
Console.WriteLine(line);
string[] parts = line.Split(',');
double x = 0.0, y = 0.0, z = 0.0;
if (double.TryParse(parts[0], out x))
{
Console.WriteLine("转换成功,值为:" + x);
}
else
{
Console.WriteLine("转换失败");
}
if (double.TryParse(parts[1], out y))
{
Console.WriteLine("转换成功,值为:" + y);
}
else
{
Console.WriteLine("转换失败");
}
if (double.TryParse(parts[2], out z))
{
Console.WriteLine("转换成功,值为:" + z);
}
else
{
Console.WriteLine("转换失败");
}
points.Add(new Point3d(x,y,z));
}
}
}
catch (FileNotFoundException)
{
Console.WriteLine("File not found: {0}", filePath);
}
catch (IOException e)
{
Console.WriteLine("Error reading file: {0}", e.Message);
}
return points;
}
}
//修改线段的高程
public class ChangeElevate
{
[CommandMethod(“ChangeElevation”)]
public void ChangeElevation()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
// 获取当前文档编辑器
// 定义文件选择器
PromptOpenFileOptions fileOpts = new PromptOpenFileOptions(“选择文件”);
fileOpts.Filter = “所有文件 (.)|.”;
// 提示用户选择文件
PromptFileNameResult fileRes = ed.GetFileNameForOpen(fileOpts);
if (fileRes.Status == PromptStatus.OK)
{
// 用户选择了文件
string filePath = fileRes.StringResult;
ed.WriteMessage("\n已选择文件:" + filePath);
List points = ReadFile.readFilePts(filePath);
List pointts = new List();
foreach (var pt in points) {
Point pp=new Point(pt.X,pt.Y,pt.Z);
pointts.Add(pp);
}
// GPSHeightFit heightfit=new GPSHeightFit(points);
//f.GPSHeightFitting gpsFit(points);
询问新的高程值
//PromptDoubleResult pdr = ed.GetDouble("\nEnter new elevation: ");
//if (pdr.Status != PromptStatus.OK) return;
//double newElevation = pdr.Value;
// 选择要更改的线段
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK) return;
SelectionSet ss = psr.Value;
string path = "C:/Users/Administrator/Desktop/CadTmp/";
string rmControlPath = string.Format("{0}/heightControl.csv", path);
// 开始事务处理
List startpts = new List();
List newstartpts = new List();
List endpts = new List();
List newendpts = new List();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (SelectedObject so in ss)
{
Entity ent = (Entity)tr.GetObject(so.ObjectId, OpenMode.ForWrite);
if (ent is Line)
{
Line line = (Line)ent;
startpts.Add(line.StartPoint);
endpts.Add(line.EndPoint);
// 修改线段的起始和结束点高程
double newStartZ = Interpolate.QuadraticInterpolation(pointts,line.StartPoint.X, line.StartPoint.Y);
line.StartPoint = new Point3d(line.StartPoint.X, line.StartPoint.Y, newStartZ);
double neweNDZ = Interpolate.QuadraticInterpolation(pointts,line.EndPoint.X, line.EndPoint.Y);
line.EndPoint = new Point3d(line.EndPoint.X, line.EndPoint.Y, neweNDZ);
newstartpts.Add(line.StartPoint);
newendpts.Add(line.EndPoint);
修改线段的起始和结束点高程
//double newStartZ3 = Interpolate.CubicInterpolation(pointts, line.StartPoint.X, line.StartPoint.Y);
//line.StartPoint = new Point3d(line.StartPoint.X, line.StartPoint.Y, newStartZ3);
//double neweNDZ3 = Interpolate.CubicInterpolation(pointts, line.EndPoint.X, line.EndPoint.Y);
//line.EndPoint = new Point3d(line.EndPoint.X, line.EndPoint.Y, neweNDZ3);
//int CCC = 0;
}
else if (ent is Polyline || ent is Polyline2d || ent is Polyline3d)
{
// 将实体转换为多段线
Polyline pline = (Polyline)ent;
// 遍历多段线的所有顶点
for (int i = 0; i < pline.NumberOfVertices; i++)
{
Point3d vertex = pline.GetPoint3dAt(i);
//double newStartZ = Interpolation.Interpolate(points, vertex.X, vertex.Y);
//pline.SetPointAt(i, new Point2d(vertex.X, vertex.Y));
//pline.SetBulgeAt(i,newStartZ);
}
// 更新多段线
//pline.Update();
}
}
// 提交更改
tr.Commit();
// 写新控制点文件
// 写入CSV文件
using (StreamWriter writer = new StreamWriter(rmControlPath))
{
for (int i=0;i
}
public class GetControl
{
[CommandMethod(“GetControlPts”)]
public void GetControlPts()
{
//获取当前文档对象
Document doc = Application.DocumentManager.MdiActiveDocument;
//锁文档
//doc.LockDocument();
//获取当前数据库
Database db = doc.Database;
//获取编辑文档
Editor ed = doc.Editor;
// 选择要读取的控制点信息
//;
ed.WriteMessage(“请选择需要提取的对象,其中圆和多段线类型实体会被认为是高程点 文本类型会被认为是高程注记”);
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status != PromptStatus.OK) return;
SelectionSet ss = psr.Value;
//获取搜索的阈值 超出阈值的不要
// 选择要读取的控制点信息
//;
ed.WriteMessage("请选择高程注记搜索的阈值,找不到高程注记的控制点会被丢弃");
PromptDoubleResult psrDouble = ed.GetDouble("请选择高程注记搜索的阈值,找不到高程注记的控制点会被丢弃(50)");
double distLimit = 0.0;
if (psrDouble.Status != PromptStatus.OK) return;
distLimit = psrDouble.Value;
//获取搜索的阈值 超出阈值的不要
// 选择要读取的控制点信息
//;
ed.WriteMessage("正态分布剔除错误值");
PromptDoubleResult psrDoubleRm = ed.GetDouble("输入正态分布剔除错误值区间(一个标准差约68.2% 两个约95.4% 三个能达到99.7%):(3) ");
double psRm = 0.0; //西格玛 区间
if (psrDoubleRm.Status != PromptStatus.OK) return;
psRm = psrDoubleRm.Value;
//PromptSaveFileOptions pr = new PromptSaveFileOptions("选择保存路径:");
//PromptFileNameResult saveRes= ed.GetFileNameForSave(pr);
//if (saveRes.Status != PromptStatus.OK)
//{
// ed.WriteMessage("not select save!");
// return;
//}
//string path = saveRes.ToString();
// 开始事务处理
string path = "C:/Users/Administrator/Desktop/CadTmp/";
using (Transaction tr = db.TransactionManager.StartTransaction())
{
List controlPts = new List();
List markPts = new List();
List newControlPts = new List();
List dists = new List();
List textZs = new List();
//获取所有的控制点
foreach (SelectedObject so in ss)
{
//获取当前对象用于读取信息
Entity ent = (Entity)tr.GetObject(so.ObjectId, OpenMode.ForRead);
if (ent is Circle)
{
Circle line = (Circle)ent;
// 修改线段的起始和结束点高程
Point3d circleCenter = line.Center;
controlPts.Add(circleCenter);
}
else if (ent is Polyline || ent is Polyline2d || ent is Polyline3d)
{
// 将实体转换为多段线
Polyline pline = (Polyline)ent;
int ccount = pline.NumberOfVertices;
// 遍历多段线的所有顶点
double x = 0.0, y = 0.0, z = 0.0;
for (int i = 0; i < pline.NumberOfVertices; i++)
{
Point3d vertex = pline.GetPoint3dAt(i);
x += vertex.X;
y += vertex.Y;
z += vertex.Z;
}
Point3d circleCenter = new Point3d(x / ccount, y / ccount, z / ccount);
controlPts.Add(circleCenter);
// 更新多段线
//pline.Update();
}
else {
}
}
//获取所有的注记
//获取所有的控制点
foreach (SelectedObject so in ss)
{
//获取当前对象用于读取信息
Entity ent = (Entity)tr.GetObject(so.ObjectId, OpenMode.ForRead);
if (ent is DBText)
{
//如果是单行文本
DBText line = (DBText)ent;
if (line!=null) {
Point3d circleCenter = line.Position;
string value= line.TextString;
// 定义一个小数匹配的正则表达式
string pattern = @"^-?\d+(?:\.\d+)?$";
// 创建一个正则表达式实例,并进行匹配
Regex regex = new Regex(pattern);
if (regex.IsMatch(value))
{
// 匹配成功,字符串是一个小数
double number = double.Parse(value);
textZs.Add(number);
if (number < 500 || number > 1500)
{
int ccc = 0;
}
Point3d newCenter = new Point3d(circleCenter.X,circleCenter.Y,number);
markPts.Add(newCenter);
Console.WriteLine(number);
}
else
{
// 匹配失败,字符串不是一个小数
Console.WriteLine("不是一个小数");
}
//markPts.Add(circleCenter);
}
// 修改线段的起始和结束点高程
//Point3d circleCenter = line.Center;
//controlPts.Add(circleCenter);
}
else if (ent is MText)
{
//如果是多行文本
MText line = (MText)ent;
if (line != null)
{
Point3d circleCenter = line.Location;
markPts.Add(circleCenter);
}
}
else
{
}
}
//每个控制点匹配高程
KdTree kdTree = new KdTree(markPts);
int count = controlPts.Count();
for (int i = 0; i < count; ++i)
{
Point3d target = controlPts[i];
Point3d nearestNeighbor = kdTree.FindNearestNeighbor(target);
double dist = kdTree.Distance(target, nearestNeighbor);
dists.Add(dist);
if (dist > distLimit) continue;
Point3d newPt=new Point3d(target.X, target.Y, nearestNeighbor.Z);
newControlPts.Add(newPt);
}
//处理控制点 剔除粗差
List rmpts = RemoveOutlier.RemoveOutliers(newControlPts, psRm);
List rmdupPts = new List();
if (rmpts.Count() > 0)
{
rmdupPts.Add(rmpts[0]);
}
for (int i = 0; i < rmpts.Count(); ++i)
{
bool isFind = false;
for (int j = 0; j < rmdupPts.Count(); ++j)
{
double dist = kdTree.Distance(rmpts[i], rmdupPts[j]);
if (dist < 10) isFind = true;
}
if (!isFind)
{
rmdupPts.Add(rmpts[i]);
}
}
// 写控制点文件
string controlPath = string.Format("{0}/control.csv", path); //获取的所有控制点
string newcontrolPath = string.Format("{0}/newControl.csv", path); //获取高程后的控制点
string markPath = string.Format("{0}/mark.csv", path); //获取的高程标注
string distPath = string.Format("{0}/markdist.csv", path); //控制点和高程标准匹配距离
string zsPath = string.Format("{0}/textzs.csv", path); //提取的高程注记Z值
string rmControlPath = string.Format("{0}/rmControl.csv", path); //正态分布去除两端的高程点
string rmdupControlPath = string.Format("{0}/rmDupControl.csv", path); //去除重复值的高程点
// 写入CSV文件
using (StreamWriter writer = new StreamWriter(controlPath))
{
foreach (Point3d rowData in controlPts)
{
string row = string.Format("{0:F6},{1:F6},{2:F6}", rowData.X, rowData.Y, rowData.Z);
writer.WriteLine(row);
}
}
Console.WriteLine("control CSV file has been written.");
// 写标记点文件
using (StreamWriter writer = new StreamWriter(markPath))
{
foreach (Point3d rowData in markPts)
{
string row = string.Format("{0:F6},{1:F6},{2:F6}", rowData.X, rowData.Y, rowData.Z);
writer.WriteLine(row);
}
}
Console.WriteLine("control CSV file has been written.");
// 写新控制点文件
// 写入CSV文件
using (StreamWriter writer = new StreamWriter(newcontrolPath))
{
foreach (Point3d rowData in newControlPts)
{
string row = string.Format("{0:F6},{1:F6},{2:F6}", rowData.X, rowData.Y, rowData.Z);
writer.WriteLine(row);
}
}
Console.WriteLine("control CSV file has been written.");
// 写新控制点文件
// 写入CSV文件
using (StreamWriter writer = new StreamWriter(distPath))
{
foreach (double rowData in dists)
{
string row = string.Format("{0:F6}", rowData);
writer.WriteLine(row);
}
}
Console.WriteLine("control CSV file has been written.");
// 写新控制点文件
// 写入CSV文件
using (StreamWriter writer = new StreamWriter(rmControlPath))
{
foreach (Point3d rowData in rmpts)
{
string row = string.Format("{0:F6},{1:F6},{2:F6}", rowData.X, rowData.Y, rowData.Z);
writer.WriteLine(row);
}
}
// 写新控制点文件
// 写入CSV文件
using (StreamWriter writer = new StreamWriter(rmdupControlPath))
{
foreach (Point3d rowData in rmdupPts)
{
string row = string.Format("{0:F6},{1:F6},{2:F6}", rowData.X, rowData.Y, rowData.Z);
writer.WriteLine(row);
}
}
Console.WriteLine("control CSV file has been written.");
}
ed.WriteMessage("\nLine elevation changed.");
//解锁文档
// doc.Dispose();
}
}`