Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 2
0
        /// <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();
                            }
                        }
                    }
                }
            }
        }