Question

J'ai une path gréométrie que j'ai construite à partir d'un tas de lingese, et je veux la diviser en deux path gigantesométries divisées par une ligne intersectant au milieu de la géométrie.Voici ce que je veux dire par cette image:

http://i30.tinypic.com/2noyvm.png

Je peux passer à travers les linéaires et créer un tableau d'objets de ligne simples (objet simple avec une propriété Point1, point2 de manière à ce qu'il représente une ligne).Mais je dois en quelque sorte comprendre quelles lignes étaient à une extrémité de la ligne intersective et quelles lignes étaient à l'autre extrémité de la ligne d'intersect ...

Ceci est un peu comme l'opposé d'une méthode de combinaison de géométrie, quelque chose comme une méthode de division de géométrie que j'essaie de mettre ensemble.

Des idées?

merci!

Était-ce utile?

La solution

Eh bien, c'était amusant, voici ce que j'ai fait (Honnêtement, je n'ai aucune idée s'il s'agit du moyen "droit" de s'il y a une voie plus efficace).

  1. Créez une transformation qui déplace la géométrie de sorte que la ligne de division soit sur l'axe des Y.
  2. pour chaque ligne dans la géométrie - si x <0 c'est à gauche, si x> 0 C'est à droite, si la ligne traverse l'axe Y la divise en deux lignes.
  3. Transformez les deux listes de lignes à l'aide de l'inverse de la transformation de l'étape 1 et de reconstruire une géométrie d'eux.
  4. Voici une méthode de scissionométrie qui prend une géométrie et une ligne définie par deux points et renvoie les deux géométries:

        private void SplitGeometry(Geometry geo, Point pt1, Point pt2, out PathGeometry leftGeo, out PathGeometry rightGeo)
        {
            double c = 360.0 + 90.0 - (180.0 / Math.PI * Math.Atan2(pt2.Y - pt1.Y, pt2.X - pt1.X));
            var t = new TransformGroup();
            t.Children.Add(new TranslateTransform(-pt1.X, -pt1.Y));
            t.Children.Add(new RotateTransform(c));
            var i = t.Inverse;
            leftGeo = new PathGeometry();
            rightGeo = new PathGeometry();
            foreach (var figure in geo.GetFlattenedPathGeometry().Figures)
            {
                var left = new List<Point>();
                var right = new List<Point>();
                var lastPt = t.Transform(figure.StartPoint);
                foreach (PolyLineSegment segment in figure.Segments)
                {
                    foreach (var currentPtOrig in segment.Points)
                    {
                        var currentPt = t.Transform(currentPtOrig);
                        ProcessLine(lastPt, currentPt, left, right);
                        lastPt = currentPt;
                    }
                }
                ProcessFigure(left, i, leftGeo);
                ProcessFigure(right, i, rightGeo);
            }
        }
    
        private void ProcessFigure(List<Point> points, GeneralTransform transform, PathGeometry geometry)
        {
            if (points.Count == 0) return;
            var result = new PolyLineSegment();
            var prev = points[0];
            for (int i = 1; i < points.Count; ++i)
            {
                var current = points[i];
                if (current == prev) continue;
                result.Points.Add(transform.Transform(current));
                prev = current;
            }
            if (result.Points.Count == 0) return;
            geometry.Figures.Add(new PathFigure(transform.Transform(points[0]), new PathSegment[] { result }, true));
        }
    
        private void ProcessLine(Point pt1, Point pt2, List<Point> left, List<Point> right)
        {
            if (pt1.X >= 0 && pt2.X >= 0)
            {
                right.Add(pt1);
                right.Add(pt2);
            }
            else if (pt1.X < 0 && pt2.X < 0)
            {
                left.Add(pt1);
                left.Add(pt2);
            }
            else if (pt1.X < 0)
            {
                double c = (Math.Abs(pt1.X) * Math.Abs(pt2.Y - pt1.Y)) / Math.Abs(pt2.X - pt1.X);
                double y = pt1.Y + c * Math.Sign(pt2.Y - pt1.Y);
                var p = new Point(0, y);
                left.Add(pt1);
                left.Add(p);
                right.Add(p);
                right.Add(pt2);
            }
            else
            {
                double c = (Math.Abs(pt1.X) * Math.Abs(pt2.Y - pt1.Y)) / Math.Abs(pt2.X - pt1.X);
                double y = pt1.Y + c * Math.Sign(pt2.Y - pt1.Y);
                var p = new Point(0, y);
                right.Add(pt1);
                right.Add(p);
                left.Add(p);
                left.Add(pt2);
            }
        }
    

Autres conseils

Le moyen de déterminer quelles lignes sont de quel côté de la ligne d'intersection consiste à calculer le signe du déterminant des points d'extrémité de ligne par rapport à la ligne d'intersection.Positif est un côté, le négatif est l'autre.

Si vous souhaitez avoir une intersection plus sophistiquée, dites-vous, à l'intérieur d'un segment de ligne, vous devez créer un graphique d'arêtes et de verxes doublement dirigés et calculez l'intersection de la ligne d'intersection et de chaque bord de polygone.Vous insérez ensuite des sommets où la ligne intersecte les bords et retracez le graphique, construisant un polygone à partir des bords dirigés lorsque vous suivez l'une à l'autre.

Si vous recherchez une implémentation de cela, consultez Suite de topologie nette ,Ce qui, tout en utilisé principalement pour SIG, est également utile pour des problèmes généraux de géométrie informatique comme celle-ci.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top