private double CalSimilarity(List <CCorrCpts> pCorrCptsLt) { //数据准备 //X、Y的差值 double[] dblFrDiffX = new double[pCorrCptsLt.Count - 1]; double[] dblFrDiffY = new double[pCorrCptsLt.Count - 1]; double[] dblToDiffX = new double[pCorrCptsLt.Count - 1]; double[] dblToDiffY = new double[pCorrCptsLt.Count - 1]; for (int i = 0; i < pCorrCptsLt.Count - 1; i++) { dblFrDiffX[i] = pCorrCptsLt[i + 1].FrCpt.X - pCorrCptsLt[i].FrCpt.X; dblFrDiffY[i] = pCorrCptsLt[i + 1].FrCpt.Y - pCorrCptsLt[i].FrCpt.Y; dblToDiffX[i] = pCorrCptsLt[i + 1].ToCpt.X - pCorrCptsLt[i].ToCpt.X; dblToDiffY[i] = pCorrCptsLt[i + 1].ToCpt.Y - pCorrCptsLt[i].ToCpt.Y; } //各线段长度 double[] dblFrDis = new double[pCorrCptsLt.Count - 1]; double[] dblToDis = new double[pCorrCptsLt.Count - 1]; for (int i = 0; i < pCorrCptsLt.Count - 1; i++) { dblFrDis[i] = Math.Sqrt(dblFrDiffX[i] * dblFrDiffX[i] + dblFrDiffY[i] * dblFrDiffY[i]); dblToDis[i] = Math.Sqrt(dblToDiffX[i] * dblToDiffX[i] + dblToDiffY[i] * dblToDiffY[i]); } //Fr线段和To线段之间的角度差(设定为必然小于180度,用余弦求) double[] dblDiffAngle = new double[pCorrCptsLt.Count - 1]; for (int i = 0; i < pCorrCptsLt.Count - 1; i++) { dblDiffAngle[i] = CGeoFunc.CalAngle(dblFrDiffX[i], dblFrDiffY[i], dblToDiffX[i], dblToDiffY[i]); } //计算最终的值 double dblSumNumerator = 0; double dblSumDenominator = 0; //double dblSumDenominator = dblFrAngle[0] * (dblFrDis[pCorrCptsLt.Count - 2] + dblFrDis[0]) + dblToAngle[0] * (dblToDis[pCorrCptsLt.Count - 2] + dblToDis[0]); for (int i = 0; i < pCorrCptsLt.Count - 1; i++) { dblSumNumerator += dblDiffAngle[i] * (dblFrDis[i] + dblToDis[i]); //dblSumDenominator += dblFrAngle[i] * (dblFrDis[i-1] + dblFrDis[i]) + dblToAngle[i] * (dblToDis[i-1] + dblToDis[i]); dblSumDenominator += dblFrDis[i] + dblToDis[i]; } double dblSimilarity = 1 - dblSumNumerator / (Math.PI * dblSumDenominator); return(dblSimilarity); }
public void RightAngelSimplification(CPolyline cpl, ref List <CPolyline> Cpllt, double dblThreshold, double verysmall) { // step1 首先顾及直角,对于每一条polyline,遍历线的除首尾点以外的点,找出夹角为90°±5°的特殊顶点 double dblAngelThreshold = Convert.ToDouble(this.TxtAngelThreshold.Text); List <CPoint> CptLt = new List <CPoint>(); for (int i = 1; i < cpl.CptLt.Count - 1; i++) { List <CPoint> cptlt = new List <CPoint>(); // Step2 求各个特殊顶点包括扩展边在内的临边,主要是求扩展边 if (Math.Abs(CGeoFunc.CalAngle(cpl.CptLt[i - 1], cpl.CptLt[i], cpl.CptLt[i + 1]) - Math.PI / 2) <= dblAngelThreshold * Math.PI / 180) { cptlt.Add((cpl.CptLt[i - 1])); cptlt.Add((cpl.CptLt[i + 1])); for (int j = i - 1; j > 0; j--) { if (CGeoFunc.CalAngle(cpl.CptLt[i - 1], cpl.CptLt[i], cpl.CptLt[j - 1], cpl.CptLt[j]) < dblAngelThreshold * Math.PI / 180) { cptlt.Remove(cpl.CptLt[j]); cptlt.Add(cpl.CptLt[j - 1]); } else { break; } } for (int j = i + 1; j < cpl.CptLt.Count - 1; j++) { if (CGeoFunc.CalAngle(cpl.CptLt[i], cpl.CptLt[i + 1], cpl.CptLt[j], cpl.CptLt[j + 1]) < dblAngelThreshold * Math.PI / 180) { cptlt.Remove(cpl.CptLt[j]); cptlt.Add(cpl.CptLt[j + 1]); } else { break; } } } //Step3 找出各个满足条件(两条邻边足够长)的特殊顶点,然后将它们视为断点进行分割 if (cptlt.Count == 2) { if (CGeoFunc.CalDis(cpl.CptLt[i], cptlt[0]) >= dblThreshold && CGeoFunc.CalDis(cpl.CptLt[i], cptlt[1]) >= dblThreshold) { CptLt.AddRange(cptlt); CptLt.Add(cpl.CptLt[i]); } } } //删除CptLt中的重复点 for (int i = 0; i < CptLt.Count; i++) { for (int j = CptLt.Count - 1; j >= i + 1; j--) { if (CptLt[i].Equals2D(CptLt[j], verysmall)) { CptLt.RemoveAt(j); } } } //分割断点 for (int i = CptLt.Count - 1; i >= 0; i--) { if (CptLt[i].Equals2D(cpl.CptLt[0], verysmall) || CptLt[i].Equals2D(cpl.CptLt[cpl.CptLt.Count - 1], verysmall)) { CptLt.RemoveAt(i); } } List <CPolyline> Cpllt1 = new List <CPolyline>(); Cpllt1.Add(cpl); for (int i = 0; i < CptLt.Count; i++) { int intnum = 0; for (int j = 0; j < Cpllt1.Count; j++) { for (int k = 1; k < Cpllt1[j].CptLt.Count - 1; k++) { if (CptLt[i].Equals2D(Cpllt1[j].CptLt[k], verysmall)) { List <CPoint> cptlt1 = new List <CPoint>(); List <CPoint> cptlt2 = new List <CPoint>(); for (int n = 0; n <= k; n++) { cptlt1.Add(Cpllt1[j].CptLt[n]); } for (int n = k; n < Cpllt1[j].CptLt.Count; n++) { cptlt2.Add(Cpllt1[j].CptLt[n]); } Cpllt1.RemoveAt(j); CPolyline cpl1 = new CPolyline(Cpllt1.Count + 1, cptlt1); Cpllt1.Add(cpl1); CPolyline cpl2 = new CPolyline(Cpllt1.Count + 2, cptlt2); Cpllt1.Add(cpl2); intnum += 1; break; } } if (intnum == 1) { break; } } } for (int i = 0; i < Cpllt1.Count; i++) { List <CPoint> cptlt0 = new List <CPoint>(); for (int j = 0; j < Cpllt1[i].CptLt.Count; j++) { CPoint cpt = new CPoint(j, (IPoint)Cpllt1[i].CptLt[j]); cptlt0.Add(cpt); } CPolyline cpl1 = new CPolyline(i, cptlt0); Cpllt.Add(cpl1); } }
private void btnRunCircle_Click(object sender, EventArgs e) { double dblRadius = Convert.ToDouble(this.txtRadius.Text); string strSelectedLayer = this.cboLayer.Text; IFeatureLayer pFeatureLayer = null; CParameterInitialize ParameterInitialize = _DataRecords.ParameterInitialize; //获取线状要素 try { for (int i = 0; i < ParameterInitialize.m_mapFeature.LayerCount; i++) { if (strSelectedLayer == ParameterInitialize.m_mapFeature.get_Layer(i).Name) { pFeatureLayer = (IFeatureLayer)ParameterInitialize.m_mapFeature.get_Layer(i); } } } catch (Exception) { MessageBox.Show("Please select a feature layer"); return; } //读取线数据 List <CPolyline> CPolylineLt = CHelpFunc.GetCPlLtByFeatureLayer(pFeatureLayer); CPolyline cpl = CPolylineLt[0]; //将线状要素分成3600份(得到3601个坐标点) List <CPoint> cptlt = new List <CPoint>(); for (int i = 0; i <= 3600; i++) { IPoint outPoint = new PointClass(); double dblRatio = Convert.ToDouble(i) / 3600; cpl.pPolyline.QueryPoint(esriSegmentExtension.esriNoExtension, dblRatio, true, outPoint); CPoint cpt = new CPoint(i, outPoint); cptlt.Add(cpt); } //将圆分成3600份(得到3601个坐标点) List <CPoint> CircleCptLt = new List <CPoint>(); double dblAdd = Math.PI / 1800; double dblHalfPI = Math.PI / 2; for (int i = 0; i <= 3600; i++) { double dblAngle = i * dblAdd; double dblCricleX = dblRadius * Math.Cos(dblAngle + dblHalfPI); //由于本方法是从“最顶上的点”开始的,因此需加“PI / 2” double dblCricleY = dblRadius * Math.Sin(dblAngle + dblHalfPI); //由于本方法是从“最顶上的点”开始的,因此需加“PI / 2” CPoint cpt = new CPoint(i, dblCricleX, dblCricleY); CircleCptLt.Add(cpt); } //由于物体是均匀的,各长度一致,因此不需定义数组 double dblFrDis = CGeoFunc.CalDis(CircleCptLt[0], CircleCptLt[1]); double dblToDis = CGeoFunc.CalDis(cptlt[0], cptlt[1]); //Fr线段和To线段之间的角度差(设定为必然小于180度,用余弦求) double[] dblDiffAngle = new double[3600]; for (int i = 0; i < 3600; i++) { dblDiffAngle[i] = CGeoFunc.CalAngle(CircleCptLt[i], CircleCptLt[i + 1], cptlt[i], cptlt[i + 1]); } //计算最终的值 double dblSumNumerator = 0; double dblSumDenominator = 0; for (int i = 0; i < 3600; i++) { dblSumNumerator += dblDiffAngle[i] * (dblFrDis + dblToDis); dblSumDenominator += dblFrDis + dblToDis; } double dblSimilarity = 1 - dblSumNumerator / (Math.PI * dblSumDenominator); MessageBox.Show(dblSimilarity.ToString()); }