示例#1
0
        public override void OnMouseMove(MouseEventArgs e, IView vw)
        {
            if (e.Button != MouseButtons.Left)
            {
                return;
            }
            if (modelView == null)
            {
                return;
            }
            int HOffset = e.X - lastPanPosition.X;
            int VOffset = e.Y - lastPanPosition.Y;

            if (VOffset != 0 || HOffset != 0)
            {
                Projection Projection = vw.Projection;
                lastPanPosition = new Point(e.X, e.Y);
                GeoVector haxis = Projection.InverseProjection * GeoVector.XAxis;
                GeoVector vaxis = Projection.InverseProjection * GeoVector.YAxis;
                ModOp     mh    = ModOp.Rotate(vaxis, SweepAngle.Deg(HOffset / 5.0));
                ModOp     mv    = ModOp.Rotate(haxis, SweepAngle.Deg(VOffset / 5.0));

                ModOp project = Projection.UnscaledProjection * mv * mh;
                // jetzt noch die Z-Achse einrichten. Die kann senkrecht nach oben oder unten
                // zeigen. Wenn die Z-Achse genau auf den Betrachter zeigt oder genau von ihm weg,
                // dann wird keine Anpassung vorgenommen, weils sonst zu sehr wackelt
                GeoVector z = project * GeoVector.ZAxis;
                if (modelView.ZAxisUp)
                {
                    const double mindeg = 0.05; // nur etwas aufrichten, aber in jedem Durchlauf
                    if (z.y < -0.1)
                    {                           // Z-Achse soll nach unten zeigen
                        Angle a = new Angle(-GeoVector2D.YAxis, new GeoVector2D(z.x, z.y));
                        if (a.Radian > mindeg)
                        {
                            a.Radian = mindeg;
                        }
                        if (a.Radian < -mindeg)
                        {
                            a.Radian = -mindeg;
                        }
                        if (z.x < 0)
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, -a.Radian);
                        }
                        else
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, a.Radian);
                        }
                        z = project * GeoVector.ZAxis;
                    }
                    else if (z.y > 0.1)
                    {
                        Angle a = new Angle(GeoVector2D.YAxis, new GeoVector2D(z.x, z.y));
                        if (a.Radian > mindeg)
                        {
                            a.Radian = mindeg;
                        }
                        if (a.Radian < -mindeg)
                        {
                            a.Radian = -mindeg;
                        }
                        if (z.x < 0)
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, a.Radian);
                        }
                        else
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, -a.Radian);
                        }
                        z = project * GeoVector.ZAxis;
                    }
                }
                // Fixpunkt bestimmen
                Point clcenter = vw.Canvas.ClientRectangle.Location;
                clcenter.X += vw.Canvas.ClientRectangle.Width / 2;
                clcenter.Y += vw.Canvas.ClientRectangle.Height / 2;
                // ium Folgenden ist Temporary auf true zu setzen und ein Mechanismus zu finden
                // wie der QuadTree von ProjektedModel berechnet werden soll
                //GeoVector newDirection = mv * mh * Projection.Direction;
                //GeoVector oldDirection = Projection.Direction;
                //GeoVector perp = oldDirection ^ newDirection;

                GeoPoint fixpoint;
                //if (Settings.GlobalSettings.ContainsSetting("ViewFixPoint"))
                if (modelView != null && modelView.FixPointValid)
                {
                    //fixpoint = (GeoPoint)Settings.GlobalSettings.GetValue("ViewFixPoint");
                    fixpoint = modelView.FixPoint;
                }
                else
                {
                    fixpoint = Projection.UnProject(clcenter);
                }
                modelView.SetViewDirection(project, fixpoint, true);
                if (Math.Abs(HOffset) > Math.Abs(VOffset))
                {
                    if (HOffset > 0)
                    {
                        vw.Canvas.Cursor = "PanEast";
                    }
                    else
                    {
                        vw.Canvas.Cursor = "PanWest";
                    }
                }
                else
                {
                    if (HOffset > 0)
                    {
                        vw.Canvas.Cursor = "PanSouth";
                    }
                    else
                    {
                        vw.Canvas.Cursor = "PanNorth";
                    }
                }
                modelView.projectedModelNeedsRecalc = false;
            }
        }
示例#2
0
        /// <summary>
        /// Constructs a non periodic spherical surface with <paramref name="center"/> and <paramref name="radius"/>. The z-axis will be oriented
        /// so that the "south pole" falls into an unused part of the sphere. The edges are <paramref name="orientedCurves"/> bound the sphere
        /// so that when you walk along the curve (<paramref name="outwardOriented"/>==true: on the outside, false: on the inside of the sphere), the
        /// used surfaces is on the left side of the curve. The curves must all be connected and define one or more closed loops on the surface.
        /// </summary>
        /// <param name="center"></param>
        /// <param name="radius"></param>
        /// <param name="outwardOriented">true: the center is on the inside, false: the center is on the outside of the surface</param>
        /// <param name="orientedCurves"></param>
        public SphericalSurfaceNP(GeoPoint center, double radius, bool outwardOriented, ICurve[] orientedCurves)
        {   // find all intersection points of the curves with a plane through the center
            // the points must be on a circle (because the curves are on the sphere) and alternating enter and leave the used surface.
            // we look for the biggest part outside the surface and use its center as the south pole
            for (int ii = 0; ii < 2; ii++)
            {   // if the first loop doesn't find a solution, run with different points again
                // exactly 3 arcs, which define an octant of the sphere can make a problem
                for (int i = 0; i < orientedCurves.Length; i++)
                {
                    double pos = 0.45;
                    if (ii == 1)
                    {
                        pos = 0.55;
                    }
                    GeoPoint  p    = orientedCurves[i].PointAt(pos); // not exactly in the middle to avoid special cases
                    GeoVector dir  = orientedCurves[i].DirectionAt(pos);
                    GeoVector xdir = p - center;
                    Plane     pln;
                    if (outwardOriented)
                    {
                        pln = new Plane(center, xdir, dir ^ xdir);
                    }
                    else
                    {
                        pln = new Plane(center, xdir, xdir ^ dir);
                    }
                    if (ii == 1)
                    {
                        pln.Modify(ModOp.Rotate(center, xdir, SweepAngle.Deg(5))); // slightly rotate to not go exactly through a vertex
                    }
                    double[] pi = orientedCurves[i].GetPlaneIntersection(pln);
                    SortedDictionary <double, bool> positions = new SortedDictionary <double, bool>();
                    bool ok = false;
                    for (int j = 0; j < pi.Length; j++)
                    {
                        GeoPoint2D pi2d = pln.Project(orientedCurves[i].PointAt(pi[j]));
                        double     a    = Math.Atan2(pi2d.y, pi2d.x);
                        if (Math.Abs(pi[j] - pos) < 1e-6)
                        {
                            ok = true;
                            a  = 0.0;
                        }
                        if (positions.ContainsKey(a))
                        {
                            ok = false;
                            break;
                        }
                        else
                        {
                            positions[a] = outwardOriented ^ (pln.ToLocal(orientedCurves[i].DirectionAt(pi[j])).z > 0);
                        }
                    }
                    if (ok)
                    {
                        for (int k = 0; k < orientedCurves.Length; k++)
                        {
                            if (k == i)
                            {
                                continue;
                            }
                            pi = orientedCurves[k].GetPlaneIntersection(pln);
                            for (int j = 0; j < pi.Length; j++)
                            {
                                GeoPoint2D pi2d = pln.Project(orientedCurves[k].PointAt(pi[j]));
                                double     a    = Math.Atan2(pi2d.y, pi2d.x);
                                if (a < 0)
                                {
                                    a += Math.PI * 2.0;
                                }
                                if (positions.ContainsKey(a))
                                {
                                    ok = false;
                                    break;
                                }
                                else
                                {
                                    positions[a] = outwardOriented ^ (pln.ToLocal(orientedCurves[k].DirectionAt(pi[j])).z > 0);
                                }
                            }
                            if (!ok)
                            {
                                break;      // two identical intersection points
                            }
                        }
                    }
                    if (ok)
                    {
                        double lastPos = -1;
                        bool   lastEnter = false;
                        double sp = 0, d = double.MinValue;
                        foreach (KeyValuePair <double, bool> position in positions)
                        {
                            if (lastPos >= 0)
                            {
                                if (position.Value == lastEnter)
                                {
                                    ok = false; // must be alternating
                                    break;
                                }
                                if (position.Value && position.Key - lastPos > d)
                                {
                                    d  = position.Key - lastPos;
                                    sp = lastPos;
                                }
                            }
                            lastPos   = position.Key;
                            lastEnter = position.Value;
                        }
                        GeoPoint2D soutPole2d = new GeoPoint2D(radius * Math.Cos(sp + d / 2), radius * Math.Sin(sp + d / 2));
                        if (ok && d > double.MinValue)
                        {
                            this.center = center;
                            zAxis       = center - pln.ToGlobal(soutPole2d);
                            zAxis.ArbitraryNormals(out xAxis, out yAxis);
                            if (!outwardOriented)
                            {
                                xAxis = -xAxis;
                            }
                            xAxis.Length = zAxis.Length;
                            yAxis.Length = zAxis.Length;
                        }
                        else
                        {
                            ok = false;
                        }
                    }
#if DEBUG
                    // GeoObjectList dbg = DebugGrid;
#endif
                    if (ok)
                    {
                        return;
                    }
                }
            }
        }