Beispiel #1
0
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            if (mTimerTicks == 0)
            {
                timeTick.Start();
            }
            else
            {
                timeTick.Stop();
                timeTick.Start();
            }
            mTimerTicks++;
            System.Drawing.Point point = this.PointToClient(Control.MousePosition);     //放大中心点屏幕坐标
            PointF  temp           = new PointF(point.X, point.Y);
            RgPoint p              = mScreenDisplay.DisplayTransformation.ToUnit(temp); //对应的当前Zoom下的世界坐标
            float   wheeldeltatick = 120;
            float   zoomdelta      = (1.25f * (Math.Abs(e.Delta) / wheeldeltatick));

            if (e.Delta < 0)
            {
                mScreenDisplay.DisplayTransformation.Zoom = mScreenDisplay.DisplayTransformation.Zoom / zoomdelta;
            }
            else
            {
                mScreenDisplay.DisplayTransformation.Zoom = mScreenDisplay.DisplayTransformation.Zoom * zoomdelta;
            }
            //float centerX = ClientRectangle.Width / 2;
            //float centerY = ClientRectangle.Height / 2;
            //RgPoint p2 = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(centerX, centerY));//对应的当前Zoom下的世界坐标
            //SetCenterScreen(mScreenDisplay.DisplayTransformation.ToScreen(p2), false);
            ZoomScreen(mScreenDisplay.DisplayTransformation.ToScreen(p), temp, false);//放大后,得到同一个世界坐标对应的屏幕坐标
            base.OnMouseWheel(e);
        }
Beispiel #2
0
        void mMapControl_MouseMove(object sender, MouseEventArgs e)
        {
            RgPoint pt = mMapControl.ScreenDisplay.DisplayTransformation.ToUnit(new PointF(e.X, e.Y));

            x = Math.Round(pt.X, 3);
            y = Math.Round(pt.Y, 3);
        }
Beispiel #3
0
        /// <summary>
        /// 设置画布到屏幕的中心
        /// </summary>
        /// <param name="rPoint">直角坐标系坐标</param>
        public void SetCenter(RgPoint unitPoint)
        {
            //将unitPoint点对应到屏幕上point
            PointF point = mScreenDisplay.DisplayTransformation.ToScreen(unitPoint);

            m_lastCenterPoint = unitPoint;
            //将unitPoint偏移到屏幕中心
            SetCenterScreen(point, false);
        }
Beispiel #4
0
        public RgPoint CenterPointUnit()
        {
            RgPoint p1     = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(0, 0));
            RgPoint p2     = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(this.ClientRectangle.Width, this.ClientRectangle.Height));
            RgPoint center = new RgPoint();

            center.X = (p1.X + p2.X) / 2;
            center.Y = (p1.Y + p2.Y) / 2;
            return(center);
        }
Beispiel #5
0
        //===================================================================
        // 点到直线距离(垂直距离)
        // dist_Point_to_Line(): get the distance of a point to a line
        //     Input:  a Point P and a Line L (in any dimension)
        //     Return: the shortest distance from P to L
        public static double dist_Point_to_Line(Point3D P, RgLine L)
        {
            Vector3d v  = L.P1 - L.P0;
            Vector3d w  = P - L.P0;
            double   c1 = RgMath.dot(w, v);
            double   c2 = RgMath.dot(v, v);
            double   b  = c1 / c2;
            RgPoint  Pb = L.P0 + b * v;

            return(RgMath.d(P, Pb));
        }
Beispiel #6
0
 /// <summary>
 /// Returns true if this instance touches the <see cref="RgPoint"/>
 /// </summary>
 /// <param name="p">Geometry</param>
 /// <returns>True if touches</returns>
 public bool Touches(RgPoint p)
 {
     for (uint cIndex = 0; cIndex < 2; cIndex++)
     {
         if ((Min[cIndex] > p[cIndex] && Min[cIndex] < p[cIndex]) ||
             (Max[cIndex] > p[cIndex] && Max[cIndex] < p[cIndex]))
         {
             return(true);
         }
     }
     return(false);
 }
Beispiel #7
0
 private void UcMapControl_Resize(object sender, EventArgs e)
 {
     (mScreenDisplay as RGeos.Display.ScreenDisplay).ControlResized();
     if (m_lastCenterPoint != null && Width != 0)
     {
         SetCenterScreen(mScreenDisplay.DisplayTransformation.ToScreen(m_lastCenterPoint), false);
     }
     //
     m_lastCenterPoint = CenterPointUnit();
     (mScreenDisplay as RGeos.Display.ScreenDisplay).UpdateWindow();
     Invalidate();
 }
Beispiel #8
0
        //
        public bool PointInObject(RgPoint point)
        {
            float thWidth = 1;

            for (int i = 1; i < Vertices.Count; i++)
            {
                RgPoint m_p1 = Vertices[i];
                RgPoint m_p2 = Vertices[i - 1];
                return(HitUtil.IsPointInLine(m_p1, m_p2, point, thWidth));
            }
            return(false);
        }
Beispiel #9
0
        /// <summary>
        /// 当前对象是否在包围盒内
        /// </summary>
        /// <param name="rect"></param>
        /// <param name="anyPoint"></param>
        /// <returns></returns>
        public bool ObjectInRectangle(BoundingBox rect, bool anyPoint)
        {
            BoundingBox boundingrect = GetBoundingBox();

            if (anyPoint)
            {
                for (int i = 1; i < Vertices.Count; i++)
                {
                    RgPoint m_p1 = Vertices[i];
                    RgPoint m_p2 = Vertices[i - 1];
                    return(HitUtil.LineIntersectWithRect(m_p1, m_p2, rect));
                }
            }
            return(rect.Contains(boundingrect));
        }
Beispiel #10
0
        private void tspOpenRaster_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            dlg.Title  = "打开影像数据...";
            dlg.Filter = "Img格式(*.img)|*.img|GeoTiff格式(*.tif)|*.tif";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string      filename = dlg.FileName;
                RasterLayer layer    = new RasterLayer("VirtualRasterTable", filename);
                RgPoint     center   = (layer.Envelope.BottomLeft + layer.Envelope.TopRight) / 2;
                mMapControl.SetCenter(center);

                (mMapControl.ScreenDisplay as ScreenDisplay).UpdateWindow();
                mMapControl.Map.AddLayer(layer);
            }
        }
Beispiel #11
0
        /// <summary>
        /// Returns true of the Point 'p' is within the instance of this ring
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public bool IsPointWithin(RgPoint p)
        {
            bool c = false;

            for (int i = 0, j = Vertices.Count - 1; i < Vertices.Count; j = i++)
            {
                if ((((Vertices[i].Y <= p.Y) && (p.Y < Vertices[j].Y)) ||
                     ((Vertices[j].Y <= p.Y) && (p.Y < Vertices[i].Y))) &&
                    (p.X <
                     (Vertices[j].X - Vertices[i].X) * (p.Y - Vertices[i].Y) / (Vertices[j].Y - Vertices[i].Y) +
                     Vertices[i].X))
                {
                    c = !c;
                }
            }
            return(c);
        }
        /// <summary>
        /// 角平分线上点
        /// V0-V1-V2,角V0V1V2
        /// </summary>
        /// <param name="V0">起点</param>
        /// <param name="V1">中间点</param>
        /// <param name="V2">终点</param>
        /// <param name="dLength">角平分线上的截距</param>
        /// <returns></returns>
        public RgPoint Bisector(Vector3d V0, Vector3d V1, Vector3d V2, double dLength)
        {
            RgPoint pt1 = new RgPoint(V0);
            RgPoint pt2 = new RgPoint(V1);
            RgPoint pt3 = new RgPoint(V2);
            //通过象限角来求中平分线
            double dJ2   = RgMath.GetQuadrantAngle(V2.X - V1.X, V2.Y - V1.Y); //第二条线的象限角
            double dJ1   = RgMath.GetQuadrantAngle(V1.X - V0.X, V1.Y - V0.Y); //第一条线的象限角
            double dJ    = 0.0;                                               //中分线的象限角
            int    bLeft = RgMath.isLeft(pt1, pt2, pt3);
            double dJZ   = RgMath.GetIncludedAngle(pt1, pt2, pt3);            //计算夹角

            dJZ = Math.PI - dJZ;
            if (bLeft > 0)
            {
                dJ = dJ2 + dJZ / 2;
                if (dJ < 0)
                {
                    dJ = 2 * Math.PI + dJ;
                }
                if (dJ > 2 * Math.PI)
                {
                    dJ = dJ - 2 * Math.PI;
                }
            }
            else
            {
                dJ = dJ2 - dJZ / 2;
                if (dJ < 0)
                {
                    dJ = 2 * Math.PI + dJ;
                }
                if (dJ > 2 * Math.PI)
                {
                    dJ = dJ - 2 * Math.PI;
                }
            }
            double  dx  = dLength * Math.Cos(dJ);
            double  dy  = dLength * Math.Sin(dJ);
            RgPoint res = new RgPoint();

            res.X = pt2.X + dx;
            res.Y = pt2.Y + dy;
            return(res);
        }
Beispiel #13
0
        /// <summary>
        /// 点在多边形中
        /// </summary>
        /// <param name="rPt"></param>
        /// <param name="rLine"></param>
        /// <returns></returns>
        public static bool IsInPolygon(RgPoint rPt, Polygon rPolygon)
        {
            //List<RgPoint> poly = new List<RgPoint>();
            //for (int i = 0; i < rPolygon.ExteriorRing.NumPoints; i++)
            //{
            //    poly.Add(rPolygon.ExteriorRing.Point(i));
            //}
            //return IsInPolygon(poly, rPt);
            int n = rPolygon.ExteriorRing.NumPoints;

            RgPoint[] poly = new RgPoint[n + 1];
            for (int i = 0; i < rPolygon.ExteriorRing.NumPoints; i++)
            {
                poly[i] = rPolygon.ExteriorRing.Point(i);
            }
            poly[n] = rPolygon.ExteriorRing.Point(0);
            return(cn_PnPoly(rPt, poly, n) == 1 ? true : false);
        }
Beispiel #14
0
        /// <summary>
        /// Computes the minimum distance between this BoundingBox and a <see cref="RgPoint"/>
        /// </summary>
        /// <param name="p"><see cref="RgPoint"/> to calculate distance to.</param>
        /// <returns>Minimum distance.</returns>
        public virtual double Distance(RgPoint p)
        {
            double ret = 0.0;

            for (uint cIndex = 0; cIndex < 2; cIndex++)
            {
                if (p[cIndex] < Min[cIndex])
                {
                    ret += Math.Pow(Min[cIndex] - p[cIndex], 2.0);
                }
                else if (p[cIndex] > Max[cIndex])
                {
                    ret += Math.Pow(p[cIndex] - Max[cIndex], 2.0);
                }
            }

            return(Math.Sqrt(ret));
        }
Beispiel #15
0
 /// <summary>
 /// Initializes a new Bounding Box based on the bounds from a set of bounding boxes
 /// </summary>
 /// <param name="objects">list of objects</param>
 public BoundingBox(Collection <BoundingBox> objects)
 {
     if (objects.Count == 0)
     {
         _Max = null;
         _Min = null;
     }
     else
     {
         _Min = objects[0].Min.Clone();
         _Max = objects[0].Max.Clone();
         for (int i = 1; i < objects.Count; i++)
         {
             _Min.X = Math.Min(objects[i].Min.X, Min.X);
             _Min.Y = Math.Min(objects[i].Min.Y, Min.Y);
             _Max.X = Math.Max(objects[i].Max.X, Max.X);
             _Max.Y = Math.Max(objects[i].Max.Y, Max.Y);
         }
     }
 }
Beispiel #16
0
 /// <summary>
 /// Checks whether a point lies within the bounding box
 /// </summary>
 /// <param name="p">Point</param>
 /// <returns>true if point is within</returns>
 public bool Contains(RgPoint p)
 {
     if (Max.X < p.X)
     {
         return(false);
     }
     if (Min.X > p.X)
     {
         return(false);
     }
     if (Max.Y < p.Y)
     {
         return(false);
     }
     if (Min.Y > p.Y)
     {
         return(false);
     }
     return(true);
 }
Beispiel #17
0
 /// <summary>
 /// Initializes a new Bounding Box based on the bounds from a set of geometries
 /// </summary>
 /// <param name="objects">list of objects</param>
 public BoundingBox(Collection <Geometry> objects)
 {
     if (objects == null || objects.Count == 0)
     {
         _Min = null;
         _Max = null;
         return;
     }
     _Min = objects[0].GetBoundingBox().Min.Clone();
     _Max = objects[0].GetBoundingBox().Max.Clone();
     CheckMinMax();
     for (int i = 1; i < objects.Count; i++)
     {
         BoundingBox box = objects[i].GetBoundingBox();
         _Min.X = Math.Min(box.Min.X, Min.X);
         _Min.Y = Math.Min(box.Min.Y, Min.Y);
         _Max.X = Math.Max(box.Max.X, Max.X);
         _Max.Y = Math.Max(box.Max.Y, Max.Y);
     }
 }
Beispiel #18
0
        // 射线相交算法2
        //cn_PnPoly(): crossing number test for a point in a polygon
        //      Input:   P = a point,
        //               V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
        //      Return:  0 = outside, 1 = inside
        // This code is patterned after [Franklin, 2000]
        public static int cn_PnPoly(RgPoint P, RgPoint[] V, int n)
        {
            int cn = 0;    // the crossing number counter

            // loop through all edges of the polygon
            for (int i = 0; i < n; i++)
            {                                                  // edge from V[i] to V[i+1]
                if (((V[i].Y <= P.Y) && (V[i + 1].Y > P.Y)) || // an upward crossing
                    ((V[i].Y > P.Y) && (V[i + 1].Y <= P.Y)))
                {                                              // a downward crossing
                    // compute the actual edge-ray intersect x-coordinate
                    float vt = (float)((P.Y - V[i].Y) / (V[i + 1].Y - V[i].Y));
                    if (P.X < V[i].X + vt * (V[i + 1].X - V[i].X)) // P.x < intersect
                    {
                        ++cn;                                      // a valid crossing of y=P.y right of P.x
                    }
                }
            }
            return(cn & 1);     // 0 if even (out), and 1 if odd (in)
        }
Beispiel #19
0
        /// <summary>
        /// 射线相交算法1
        /// </summary>
        /// <param name="poly"></param>
        /// <param name="aPoint"></param>
        /// <returns></returns>
        public static bool IsInPolygon(List <RgPoint> poly, RgPoint aPoint)
        {
            bool flag  = false;
            int  count = poly.Count;

            if (count < 3)
            {
                return(false);
            }
            double x = poly[count - 1].X;
            double y = poly[count - 1].Y;

            for (int i = 0; i < count; i++)
            {
                double num5;
                double num6;
                double num7;
                double num8;
                if (poly[i].X > x)
                {
                    num5 = x;
                    num7 = poly[i].X;
                    num6 = y;
                    num8 = poly[i].Y;
                }
                else
                {
                    num5 = poly[i].X;
                    num7 = x;
                    num6 = poly[i].Y;
                    num8 = y;
                }
                if (((poly[i].X < aPoint.X) == (aPoint.X <= x)) && (((aPoint.Y - num6) * (num7 - num5)) < ((num8 - num6) * (aPoint.X - num5))))
                {
                    flag = !flag;
                }
                x = poly[i].X;
                y = poly[i].Y;
            }
            return(flag);
        }
Beispiel #20
0
        //===================================================================
        // 点到线段距离
        //dist_Point_to_Segment(): get the distance of a point to a segment
        //     Input:  a Point P and a Segment S (in any dimension)
        //     Return: the shortest distance from P to S,返回到线段的最短距离
        public static double dist_Point_to_Segment(Point3D P, RgSegment S)
        {
            Vector3d v  = S.P1 - S.P0;
            Vector3d w  = P - S.P0;
            double   c1 = RgMath.dot(w, v);

            if (c1 <= 0)
            {
                return(RgMath.d(P, S.P0));
            }
            double c2 = RgMath.dot(v, v);

            if (c2 <= c1)
            {
                return(RgMath.d(P, S.P1));
            }
            double  b  = c1 / c2;
            RgPoint Pb = S.P0 + b * v;

            return(RgMath.d(P, Pb));
        }
Beispiel #21
0
        /// <summary>
        /// 圆包含点
        /// </summary>
        /// <param name="center"></param>
        /// <param name="radius"></param>
        /// <param name="hitpoint"></param>
        /// <returns></returns>
        public static bool CircleHitPoint(RgPoint center, float radius, RgPoint hitpoint)
        {
            // check bounding rect, this is faster than creating a new rectangle and call r.Contains
            double leftPoint  = center.X - radius;
            double rightPoint = center.X + radius;

            if (hitpoint.X < leftPoint || hitpoint.X > rightPoint)
            {
                return(false);
            }

            double bottomPoint = center.Y - radius;
            double topPoint    = center.Y + radius;

            if (hitpoint.Y < bottomPoint || hitpoint.Y > topPoint)
            {
                return(false);
            }

            return(true);
        }
Beispiel #22
0
        void mPanel_MouseMove(object sender, MouseEventArgs e)
        {
            ISnapPoint newsnap = null;
            Point      point   = this.PointToClient(Control.MousePosition);

            RgPoint mousepoint = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(point.X, point.Y));

            //获取捕捉点
            if (RunningSnapsEnabled)
            {
                newsnap = (mMap as Map).SnapPoint(mousepoint, m_runningSnapTypes, null);
            }
            //if (newsnap == null)
            //    newsnap = mMap.GridLayer.SnapPoint(m_canvaswrapper, mousepoint, null);
            if ((m_snappoint != null) && ((newsnap == null) || (newsnap.SnapPoint != m_snappoint.SnapPoint) || m_snappoint.GetType() != newsnap.GetType()))
            {
                PointF pt1 = mScreenDisplay.DisplayTransformation.ToScreen(m_snappoint.SnapPoint);

                Rectangle invalidaterect = new Rectangle((int)pt1.X - 2, (int)pt1.Y - 2, 4, 4);
                invalidaterect.Inflate(2, 2);
                //注意查看
                mScreenDisplay.RepaintStatic(invalidaterect); // remove old snappoint
                m_snappoint = newsnap;
            }

            if (m_snappoint == null)
            {
                m_snappoint = newsnap;
            }

            if (m_snappoint != null)
            {
                RepaintSnappoint(m_snappoint);
            }
            if (CurrentTool != null)
            {
                CurrentTool.OnMouseMove(e.X, e.Y);
            }
            RgPoint pt = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(e.X, e.Y));
        }
Beispiel #23
0
 public void DrawLine(RGeos.Geometries.RgPoint p1, RGeos.Geometries.RgPoint p2, Pen pen)
 {
     if (IsStartDrawing == false)
     {
         return;
     }
     if (DrawBufferFlag == 0)
     {
         PointF v1 = mDisplayTransformation.ToScreen(p1);
         PointF v2 = mDisplayTransformation.ToScreen(p2);
         if (mBitMapGc != null)
         {
             mBitMapGc.DrawLine(pen, v1, v2);
         }
     }
     else
     {
         PointF v1 = mDisplayTransformation.ToScreen(p1);
         PointF v2 = mDisplayTransformation.ToScreen(p2);
         mDc.DrawLine(pen, v1, v2);
     }
 }
Beispiel #24
0
        public static bool LineIntersectWithRect(RgPoint lp1, RgPoint lp2, BoundingBox r)
        {
            if (r.Contains(lp1))
            {
                return(true);
            }
            if (r.Contains(lp2))
            {
                return(true);
            }

            // the rectangle bottom is top in world units and top is bottom!, confused?
            // check left
            RgPoint p3 = new RgPoint(r.Left, r.Top);
            RgPoint p4 = new RgPoint(r.Left, r.Bottom);

            if (LinesIntersect(lp1, lp2, p3, p4))
            {
                return(true);
            }
            // check bottom
            p4.Y = r.Top;
            p4.X = r.Right;
            if (LinesIntersect(lp1, lp2, p3, p4))
            {
                return(true);
            }
            // check right
            p3.X = r.Right;
            p3.Y = r.Top;
            p4.X = r.Right;
            p4.Y = r.Bottom;
            if (LinesIntersect(lp1, lp2, p3, p4))
            {
                return(true);
            }
            return(false);
        }
Beispiel #25
0
 public override void OnMouseMove(int x, int y)
 {
     if (n < 1)
     {
     }
     else
     {
         lastPoint1 = mScreenDisplay.DisplayTransformation.ToScreen(lastPoint1Unit);
         double    xmin           = Math.Min(lastPoint1.X, lastPoint2.X);
         double    ymin           = Math.Min(lastPoint1.Y, lastPoint2.Y);
         double    w              = Math.Abs(lastPoint1.X - lastPoint2.X);
         double    h              = Math.Abs(lastPoint1.Y - lastPoint2.Y);
         Rectangle invalidaterect = new Rectangle((int)xmin, (int)ymin, (int)w, (int)h);
         invalidaterect.Inflate(2, 2);
         //擦除上次的范围
         (mScreenDisplay as ScreenDisplay).RepaintStatic(invalidaterect);
         lastPoint2 = new PointF(x, y);
         RgPoint p1 = lastPoint1Unit;
         RgPoint p2 = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(x, y));
         mScreenDisplay.StartDrawing(mMapCtrl.CreateGraphics(), 1);
         mScreenDisplayDraw.DrawLine(p1, p2, Pens.Blue);
         mScreenDisplay.FinishDrawing();
     }
 }
Beispiel #26
0
        public override void OnMouseDown(int x, int y, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                n++;
                if (n <= 1)
                {
                    line = new LineString();
                    RgPoint pt = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(x, y));
                    line.Vertices.Add(pt);
                    lastPoint1Unit = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(x, y));
                    lastPoint2     = new PointF(x, y);
                }
                else
                {
                    RgPoint ptNext = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(x, y));
                    line.Vertices.Add(ptNext);
                    lastPoint1Unit = mScreenDisplay.DisplayTransformation.ToUnit(new PointF(x, y));

                    lastPoint2 = new PointF(x, y);
                    mScreenDisplay.NewObject = line;
                    mMapCtrl.Refresh();
                }
            }
            else
            {
                Carto.FetureLayer featurelyr = mMapCtrl.Map.CurrentLayer as Carto.FetureLayer;
                if (featurelyr != null && featurelyr.ShapeType == RgEnumShapeType.RgLineString)
                {
                    featurelyr.AddFeature(line);
                }
                n = 0;
                mScreenDisplay.NewObject = null;
                mMapCtrl.Refresh();
            }
        }
Beispiel #27
0
 /// <summary>
 /// 获取由两个点所形成的向量的象限角度
 /// </summary>
 /// <param name="preCoord">第一个点的坐标</param>
 /// <param name="nextCoord">第二个点的坐标</param>
 /// <returns></returns>
 public static double GetQuadrantAngle(RgPoint preCoord, RgPoint nextCoord)
 {
     return(GetQuadrantAngle(nextCoord.X - preCoord.X, nextCoord.Y - preCoord.Y));
 }
Beispiel #28
0
 /// <summary>
 /// Initializes a new Point
 /// </summary>
 /// <param name="p">2D Point</param>
 /// <param name="z">Z coordinate</param>
 public Point3D(RgPoint p, double z)
     : base(p.X, p.Y)
 {
     _Z = z;
 }
Beispiel #29
0
        /// <summary>
        /// 点在直线上
        /// </summary>
        /// <param name="rPt"></param>
        /// <param name="rLine"></param>
        /// <returns></returns>
        public static bool IsInLine(RgPoint rPt, RgLine rLine)
        {
            bool flag = false;

            return(flag);
        }
Beispiel #30
0
 /// <summary>
 /// 点是否在线段上
 /// </summary>
 /// <param name="P">任意的点</param>
 /// <param name="S">任意线段</param>
 /// <returns></returns>
 public static int In2D_Point_Segment(RgPoint P, RgSegment S)
 {
     return(0);
 }