Exemple #1
0
        /// <summary>
        /// Bestimmt den geometrischen Fehler des angegebenen Vertex in Bezug auf die
        /// Fehlerquadrik Q.
        /// </summary>
        /// <param name="v">
        /// Der Vertex, dessen geometrischer Fehler bestimmt werden soll.
        /// </param>
        /// <param name="q">
        /// Die zugrundeliegende Fehlerquadrik.
        /// </param>
        /// <returns>
        /// Der geometrische Fehler an der Stelle des angegebenen Vertex.
        /// </returns>
        double ComputeVertexError(Double3 v, Double4x4 q)
        {
            var h = new Double4(v, 1);

            //// Geometrischer Fehler Δ(v) = vᵀQv.
            return(Double4.Dot(q * h, h));
        }
Exemple #2
0
        private void SelectionRequested(SelectionFrustum obj)
        {
            if (_pos == null)
            {
                return;
            }

            // The user has interactively edited the constrained sections -> propagate the information to the simulation core
            List <int>     indices = new List <int>();
            List <Double3> pos     = _pos.GetList();

            Double4x4 trafo = _gl.SceneGraph.AbsoluteTransformation;
            //trafo.Invert();


            Double3 center = Double3.Zero;

            for (int i = 0; i < pos.Count; ++i)
            {
                double d;
                if (obj.IsPointInside(trafo.TransformPoint(pos[i]), out d))
                {
                    indices.Add(i);
                    center += pos[i];
                }
            }

            if (indices.Count > 0)
            {
                center /= indices.Count;

                SceneNode n = new SceneNode();
                n.RelativeTranslation = center;

                CoordinateSystemSceneNode cs = new CoordinateSystemSceneNode();
                //cs.RelativeTranslation = center;

                cs.Call <SceneNode>(m => m.Overlay = true);

                n.Add(cs);


                _gl.SceneGraph.Add(n);


                _sim.AddConstraint(new ConstrainedSection(cs, indices));
                _sim.UpdateConstraintConfiguration();
            }
        }
Exemple #3
0
        /// <summary>
        /// Berechnet die initialen Q-Matrizen für alle Vertices.
        /// </summary>
        /// <param name="strict">
        /// true, um eine <c>InvalidOperationException</c> zu werfen, falls ein
        /// degeneriertes Face entdeckt wird.
        /// </param>
        /// <returns>
        /// Eine Map der initialen Q-Matrizen.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Es wurde ein degeneriertes Face gefunden, dessen Vertices kollinear sind.
        /// </exception>
        Dictionary <int, Double4x4> ComputeInitialQForEachVertex(bool strict)
        {
            var q = new Dictionary <int, Double4x4>();
            // Kp Matrix für jede Ebene, d.h. jede Facette bestimmen.
            var kp = ComputeKpForEachPlane(strict);

            // Q Matrix für jeden Vertex mit 0 initialisieren.
            for (int i = 0; i < vertices.Count; i++)
            {
                q[i] = new Double4x4();
            }
            // Q ist die Summe aller Kp Matrizen der inzidenten Facetten jedes Vertex.
            for (int c = 0; c < faces.Count; c++)
            {
                var f = faces[c];
                for (int i = 0; i < 3; i++)
                {
                    q[f[i]] = q[f[i]] + kp[c];
                }
            }
            return(q);
        }
Exemple #4
0
        private void GLReady()
        {
            // Now OpenGL is ready to handle draw calls
            // Initialize the scene
            _gl.BackColor = Color.FromArgb(250, 250, 250);

            _gl.SceneGraph.Add(new CoordinateSystemGeometryScreenFixed());
            _gl.InputHandler.MouseMove += InputHandler_MouseMove;

            _pointSelectionHandler = new PointSelectionHandler(_gl.InputHandler, _gl.SceneGraph, _gl.Camera);
            _pointSelectionHandler.SelectionRequested += SelectionRequested;

            _selectionHandler             = new SelectionHandler(_gl.SceneGraph, _gl.InputHandler);
            _shiftingHandler              = new ShiftingHandler(_gl.InputHandler, _gl.Camera, _selectionHandler, true);
            _selectionHandler.MultiSelect = false;

            _gl.InputHandler.RotationMatrix = Double4x4.RotationX(0.05 * Math.PI) * Double4x4.RotationY(-0.1 * Math.PI);

            _selectionHandler.Validator = delegate(PickingResult r)
            {
                return(r.Node is SelectableSceneNode);
            };
        }
Exemple #5
0
        /// <summary>
        /// Bestimmt die Kosten für die Kontraktion der angegebenen Vertices.
        /// </summary>
        /// <param name="s">
        /// Der erste Vertex des Paares.
        /// </param>
        /// <param name="t">
        /// Der zweite Vertex des Paares.
        /// </param>
        /// <returns>
        /// Eine Instanz der Pair-Klasse.
        /// </returns>
        Pair ComputeMinimumCostPair(int s, int t)
        {
            Double3 target;
            double  cost;
            var     q = Q[s] + Q[t];
            // Siehe [Gar97], Abschnitt 4 ("Approximating Error With Quadrics").
            var m = new Double4x4()
            {
                M11 = q.M11,
                M12 = q.M12,
                M13 = q.M13,
                M14 = q.M14,
                M21 = q.M12,
                M22 = q.M22,
                M23 = q.M23,
                M24 = q.M24,
                M31 = q.M13,
                M32 = q.M23,
                M33 = q.M33,
                M34 = q.M34,
                M41 = 0,
                M42 = 0,
                M43 = 0,
                M44 = 1
            };

            // Wenn m invertierbar ist, lässt sich die optimale Position bestimmen.
            //			if (m.Determinant != 0) {
            if (Math.Abs(m.Determinant) > 1e-10)
            {
                // Determinante ist ungleich 0 für invertierbare Matrizen.
                var inv = m.Inverted(); // Matrix4d.Invert(m);
                target = new Double3(inv.M14, inv.M24, inv.M34);
                cost   = ComputeVertexError(target, q);
            }
            else
            {
                //			} else {
                // Ansonsten den besten Wert aus Position von Vertex 1, Vertex 2 und
                // Mittelpunkt wählen.
                var v1 = vertices[s];
                var v2 = vertices[t];
                var mp = new Double3()
                {
                    X = (v1.X + v2.X) / 2,
                    Y = (v1.Y + v2.Y) / 2,
                    Z = (v1.Z + v2.Z) / 2
                };
                var candidates = new[] {
                    new { cost = ComputeVertexError(v1, q), target = v1 },
                    new { cost = ComputeVertexError(v2, q), target = v2 },
                    new { cost = ComputeVertexError(mp, q), target = mp }
                };
                var best = (from p in candidates
                            orderby p.cost
                            select p).First();
                target = best.target;
                cost   = best.cost;
            }
            return(new Pair(s, t, target, cost));
        }
Exemple #6
0
        /// <summary>
        /// Berechnet die Kp-Matrix für die Ebenen aller Facetten.
        /// </summary>
        /// <param name="strict">
        /// true, um eine <c>InvalidOperationException</c> zu werfen, falls ein
        /// degeneriertes Face entdeckt wird.
        /// </param>
        /// <returns>
        /// Eine Liste von Kp-Matrizen.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Es wurde ein degeneriertes Face gefunden, dessen Vertices kollinear sind.
        /// </exception>
        IList <Double4x4> ComputeKpForEachPlane(bool strict)
        {
            var kp         = new List <Double4x4>();
            var degenerate = new List <int[]>();

            foreach (var f in faces)
            {
                var points = new[] {
                    vertices[f[0]],
                    vertices[f[1]],
                    vertices[f[2]]
                };
                // Ebene aus den 3 Ortsvektoren konstruieren.
                var dir1 = points[1] - points[0];
                var dir2 = points[2] - points[0];
                var n    = Double3.Cross(dir1, dir2);
                // Wenn das Kreuzprodukt der Nullvektor ist, sind die Richtungsvektoren
                // kollinear, d.h. die Vertices liegen auf einer Geraden und die Facette
                // ist degeneriert.
                if (n == Double3.Zero)
                {
                    degenerate.Add(f);
                    if (strict)
                    {
                        var msg = new StringBuilder()
                                  .AppendFormat("Encountered degenerate face ({0} {1} {2})",
                                                f[0], f[1], f[2])
                                  .AppendLine()
                                  .AppendFormat("Vertex 1: {0}\n", points[0])
                                  .AppendFormat("Vertex 2: {0}\n", points[1])
                                  .AppendFormat("Vertex 3: {0}\n", points[2])
                                  .ToString();
                        throw new InvalidOperationException(msg);
                    }
                }
                else
                {
                    n.Normalize();
                    var a = n.X;
                    var b = n.Y;
                    var c = n.Z;
                    var d = -Double3.Dot(n, points[0]);
                    // Siehe [Gar97], Abschnitt 5 ("Deriving Error Quadrics").
                    var m = new Double4x4()
                    {
                        M11 = a * a,
                        M12 = a * b,
                        M13 = a * c,
                        M14 = a * d,
                        M21 = a * b,
                        M22 = b * b,
                        M23 = b * c,
                        M24 = b * d,
                        M31 = a * c,
                        M32 = b * c,
                        M33 = c * c,
                        M34 = c * d,
                        M41 = a * d,
                        M42 = b * d,
                        M43 = c * d,
                        M44 = d * d
                    };
                    kp.Add(m);
                }
            }
            if (degenerate.Count > 0)
            {
                System.Diagnostics.Debug.WriteLine("Warning: {0} degenerate faces found.", degenerate.Count);
            }
            foreach (var d in degenerate)
            {
                faces.Remove(d);
            }
            return(kp);
        }
Exemple #7
0
        private void MouseMove(System.Drawing.Point pt, Double2 xy, MouseKey buttons)
        {
            if (buttons == MouseKey.Left && enabled)
            {
                if (shifting && !lockPositions)
                {
                    double  zoomNormalizedScreenHeight = camera.ZoomFactor;
                    Double2 offset = (xy - lastPos);
                    offset.X *= zoomNormalizedScreenHeight * camera.AspectRatio;
                    offset.Y *= zoomNormalizedScreenHeight;

                    Double3 o = camera.Up * offset.Y + camera.Right * offset.X;

                    for (int i = 0; i < selectionHandler.Count; ++i)
                    {
                        SelectableSceneNode node = selectionHandler[i];

                        Double4x4 m = node.AbsoluteTransformation;
                        m.ClearTranslation();
                        Double4x4 mInv = m;
                        mInv.Invert();

                        Double4x4 translation = (mInv * Double4x4.CreateTranslation(o) * m);
                        if (!xDirectionEnabled)
                        {
                            translation.M14 = 0;
                        }
                        if (!yDirectionEnabled)
                        {
                            translation.M24 = 0;
                        }
                        if (!zDirectionEnabled)
                        {
                            translation.M34 = 0;
                        }

                        node.RelativeTransformation = translation * node.RelativeTransformation;
                        OnNodeChanged(node);
                    }

                    lastPos = xy;
                }
                else if (directionEditingEnabled)
                {
                    for (int i = 0; i < selectionHandler.Count; ++i)
                    {
                        IInteractiveDirectionSceneNode n = selectionHandler[i] as IInteractiveDirectionSceneNode;
                        //object test = selectionHandler[i];
                        if (n != null)
                        {
                            if (rotateAroundViewDirectionOnly)
                            {
                                Double3 dir = selectionHandler[i].AbsoluteTransformation.Inverted().TransformDirection(camera.LookAt).Normalized();
                                n.SetEndInPlane(xy, camera, dir);
                            }
                            else
                            {
                                n.SetEnd(xy, camera);
                            }

                            OnNodeChanged(selectionHandler[i]);
                        }
                    }
                }

                if (selectionHandler.Count > 0)
                {
                    OnPositionChanged();
                }
            }
        }