/// <summary> /// 给定坐标序列,构造凸多边形 /// </summary> /// <param name="ps"></param> /// <returns></returns> public static Mesh CreateMesh(this GeoModel geoMoel, Point3Ds ps) { //顶点去重 #region List <int> wellBeRm = new List <int>(); for (int i = ps.Count - 1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (i == 0) { break; } if (ps[i].X == ps[j].X && ps[i].Y == ps[j].Y && ps[i].Z == ps[j].Z) { if (!wellBeRm.Contains(i)) { wellBeRm.Add(i); } } } } foreach (int i in wellBeRm) { ps.Remove(i); } if (ps.Count < 4) { return(null); } #endregion Mesh mesh = new Mesh(); Double[] Vertices = new Double[ps.Count * 3]; Int32[] Indexes = new Int32[3 * (ps.Count - 2)]; Double[] Normals = new Double[ps.Count * 3]; for (int i = 0; i < ps.Count; i++) { //读入坐标 Vertices[3 * i] = ps[i].X; Vertices[3 * i + 1] = ps[i].Y; Vertices[3 * i + 2] = ps[i].Z; } for (int i = 0; i < ps.Count - 2; i++) { //生成索引 Indexes[3 * i] = 0; Indexes[3 * i + 1] = i + 1; Indexes[3 * i + 2] = i + 2; //构造三角面的时候累计计算顶点法向量。顶点法向量为该点为顶点所有面的法向量之和 //给定直角坐标系的单位向量i,j,k满足下列等式: //i×j=k ; //j×k=i ; //k×i=j ; //通过这些规则,两个向量的叉积的坐标可以方便地计算出来,不需要考虑任何角度:设 //a= [a1, a2, a3] =a1i+ a2j+ a3k //b= [b1,b2,b3]=b1i+ b2j+ b3k ; //则 //a × b= [a2b3-a3b2,a3b1-a1b3, a1b2-a2b1] double a1 = Vertices[3 * (Indexes[3 * i + 1])] - Vertices[3 * (Indexes[3 * i])], a2 = Vertices[3 * (Indexes[3 * i + 1]) + 1] - Vertices[3 * (Indexes[3 * i]) + 1], a3 = Vertices[3 * (Indexes[3 * i + 1]) + 2] - Vertices[3 * (Indexes[3 * i]) + 2], b1 = Vertices[3 * (Indexes[3 * i + 2])] - Vertices[3 * (Indexes[3 * i])], b2 = Vertices[3 * (Indexes[3 * i + 2]) + 1] - Vertices[3 * (Indexes[3 * i]) + 1], b3 = Vertices[3 * (Indexes[3 * i + 2]) + 2] - Vertices[3 * (Indexes[3 * i]) + 2]; double aXb1 = a2 * b3 - a3 * b2, aXb2 = a3 * b1 - a1 * b3, aXb3 = a1 * b2 - a2 * b1; //更新法向量 //但是这算法未完善,由于现在model的各个侧面是独立的mesh,法向量累加实际上无效,依然是各个面遵循自己的方向 for (int j = 0; j < 3; j++) { Normals[3 * (Indexes[3 * i + 1])] += aXb1; Normals[3 * (Indexes[3 * i + 1]) + 1] += aXb2; Normals[3 * (Indexes[3 * i + 1]) + 2] += aXb3; } } mesh.Vertices = Vertices; mesh.Indexes = Indexes; mesh.Normals = Normals; return(mesh); }
/// <summary> /// 给定坐标序列,构造凸多边形 /// </summary> /// <param name="ps"></param> /// <returns></returns> public static Mesh CreateMesh(this GeoModel geoMoel, Point3Ds ps) { //顶点去重 #region List<int> wellBeRm = new List<int>(); for (int i = ps.Count - 1; i >= 0; i--) { for (int j = 0; j < i; j++) { if (i == 0) break; if (ps[i].X == ps[j].X && ps[i].Y == ps[j].Y && ps[i].Z == ps[j].Z) if (!wellBeRm.Contains(i)) wellBeRm.Add(i); } } foreach (int i in wellBeRm) { ps.Remove(i); } if (ps.Count < 4) return null; #endregion Mesh mesh = new Mesh(); Double[] Vertices = new Double[ps.Count * 3]; Int32[] Indexes = new Int32[3 * (ps.Count - 2)]; Double[] Normals = new Double[ps.Count * 3]; for (int i = 0; i < ps.Count; i++) { //读入坐标 Vertices[3 * i] = ps[i].X; Vertices[3 * i + 1] = ps[i].Y; Vertices[3 * i + 2] = ps[i].Z; } for (int i = 0; i < ps.Count - 2; i++) { //生成索引 Indexes[3 * i] = 0; Indexes[3 * i + 1] = i + 1; Indexes[3 * i + 2] = i + 2; //构造三角面的时候累计计算顶点法向量。顶点法向量为该点为顶点所有面的法向量之和 //给定直角坐标系的单位向量i,j,k满足下列等式: //i×j=k ; //j×k=i ; //k×i=j ; //通过这些规则,两个向量的叉积的坐标可以方便地计算出来,不需要考虑任何角度:设 //a= [a1, a2, a3] =a1i+ a2j+ a3k //b= [b1,b2,b3]=b1i+ b2j+ b3k ; //则 //a × b= [a2b3-a3b2,a3b1-a1b3, a1b2-a2b1] double a1 = Vertices[3 * (Indexes[3 * i + 1])] - Vertices[3 * (Indexes[3 * i])], a2 = Vertices[3 * (Indexes[3 * i + 1]) + 1] - Vertices[3 * (Indexes[3 * i]) + 1], a3 = Vertices[3 * (Indexes[3 * i + 1]) + 2] - Vertices[3 * (Indexes[3 * i]) + 2], b1 = Vertices[3 * (Indexes[3 * i + 2])] - Vertices[3 * (Indexes[3 * i])], b2 = Vertices[3 * (Indexes[3 * i + 2]) + 1] - Vertices[3 * (Indexes[3 * i]) + 1], b3 = Vertices[3 * (Indexes[3 * i + 2]) + 2] - Vertices[3 * (Indexes[3 * i]) + 2]; double aXb1 = a2 * b3 - a3 * b2, aXb2 = a3 * b1 - a1 * b3, aXb3 = a1 * b2 - a2 * b1; //更新法向量 //但是这算法未完善,由于现在model的各个侧面是独立的mesh,法向量累加实际上无效,依然是各个面遵循自己的方向 for (int j = 0; j < 3; j++) { Normals[3 * (Indexes[3 * i + 1])] += aXb1; Normals[3 * (Indexes[3 * i + 1]) + 1] += aXb2; Normals[3 * (Indexes[3 * i + 1]) + 2] += aXb3; } } mesh.Vertices = Vertices; mesh.Indexes = Indexes; mesh.Normals = Normals; return mesh; }
/// <summary> /// 鼠标动作Up /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void SceneControlMouseUp(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { EndOneMeasure(); } if (e.Button == MouseButtons.Left) { if (mPoint3Ds.Count == 0) { //ClearMeasureResult(); } if (mTempPoint != Point3D.Empty && mPoint3Ds.Count > 1) { mPoint3Ds.Remove(mPoint3Ds.Count - 1); mTempPoint = Point3D.Empty; } Point location = mSceneControl.PointToClient(Cursor.Position); Point3D point3D = new Point3D(); if (mSceneControl.Action == Action3D.MeasureDistance && mIndex == 8 || mSceneControl.Action == Action3D.MeasureAltitude && mIndex == 9 || mSceneControl.Action == Action3D.MeasureHorizontalDistance) { point3D = mSceneControl.Scene.PixelToGlobe(new Point(e.X, e.Y), SuperMap.Realspace.PixelToGlobeMode.TerrainAndModel); } else { point3D = mSceneControl.Scene.PixelToGlobe(new Point(e.X, e.Y)); } if (!Double.IsNaN(point3D.X) && !Double.IsNaN(point3D.Y) && !Double.IsNaN(point3D.Z)) { mPoint3Ds.Add(point3D); if (mSceneControl.Action == Action3D.MeasureHorizontalDistance || mSceneControl.Action == Action3D.MeasureDistance && mIndex == 8) { //添加部分段长度 if (!Toolkit.IsZero(mCurLength)) { if (mPoint3Ds.Count >= 2) { mPoint3Ds.RemoveRange(0, mPoint3Ds.Count - 2); String distanceUnit = "米"; GeoLine3D geoLine3D = new GeoLine3D(mPoint3Ds); TextPart3D textPart3D = new TextPart3D(); textPart3D.AnchorPoint = new Point3D(0, 0, 0); Double tempCurLength = mCurLength; textPart3D.Text = String.Format("{0:F2}{1}", tempCurLength, " " + distanceUnit); if (mPoint3Ds[0].X > 0 && mPoint3Ds[1].X > 0 || mPoint3Ds[0].X < 0 && mPoint3Ds[1].X < 0) { textPart3D.X = geoLine3D.InnerPoint3D.X; } else { textPart3D.X = 180; } textPart3D.Y = geoLine3D.InnerPoint3D.Y; textPart3D.Z = geoLine3D.InnerPoint3D.Z; GeoText3D text3d = mCurrentGeoText3DMessage == null?GetGeoText3DMessage() : mCurrentGeoText3DMessage; text3d.AddPart(textPart3D); //设置文字样式 text3d.TextStyle.FontHeight = 6; text3d.TextStyle.Alignment = TextAlignment.BottomLeft; text3d.TextStyle.BackColor = Color.Black; text3d.TextStyle.Outline = true; text3d.Style3D.AltitudeMode = AltitudeMode.Absolute; int index = mSceneControl.Scene.TrackingLayer.IndexOf(MessageTag); if (index >= 0) { mSceneControl.Scene.TrackingLayer.Remove(index); } //ClearTextMessageTag(); mSceneControl.Scene.TrackingLayer.Add(text3d, MessageTag); } } //测地形距离 else if (mSceneControl.Action == Action3D.MeasureTerrainDistance) { //添加部分段长度 if (!Toolkit.IsZero(mCurLength)) { if (mPoint3Ds.Count >= 2) { mPoint3Ds.RemoveRange(0, mPoint3Ds.Count - 2); GeoLine3D geoLine3D = new GeoLine3D(mPoint3Ds); String distanceUnit = "米"; TextPart3D textPart3D = new TextPart3D(); textPart3D.AnchorPoint = new Point3D(0, 0, 0); Double tempCurLength = mCurLength; textPart3D.Text = String.Format("{0:F2}{1}", tempCurLength, " " + distanceUnit); if (mPoint3Ds[0].X > 0 && mPoint3Ds[1].X > 0 || mPoint3Ds[0].X < 0 && mPoint3Ds[1].X < 0) { textPart3D.X = geoLine3D.InnerPoint.X; textPart3D.Y = geoLine3D.InnerPoint.Y; } else { textPart3D.X = 180; textPart3D.Y = geoLine3D.InnerPoint.Y; } textPart3D.Z = 0; GeoText3D text3d = GetGeoText3DMessage(); text3d.AddPart(textPart3D); text3d.TextStyle.FontHeight = 6; text3d.TextStyle.Alignment = TextAlignment.BottomLeft; text3d.TextStyle.BackColor = Color.Black; text3d.TextStyle.Outline = true; text3d.Style3D.AltitudeMode = AltitudeMode.ClampToGround;//贴地高程模式 ClearTextMessageTag(); mSceneControl.Scene.TrackingLayer.Add(text3d, MessageTag); } } } else if (mSceneControl.Action == Action3D.MeasureArea && mIndex == 10) { } else if (mSceneControl.Action == Action3D.MeasureAltitude && mIndex == 9) { //清除量算高度信息 if (!(Toolkit.IsZero(mCurAltitude))) { EndOneMeasure(); } } } } } }