Domanda

Ho una patchometria che ho costruito da un gruppo di linee di linea, e voglio dividerlo in due patgeometries diviso da una linea che si interseca nel mezzo della geometria.Ecco cosa intendo con questa immagine:

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

Posso passare attraverso i LineeGments e creare una serie di oggetti di linea semplici (oggetto semplice w / A POINT1, Proprietà Point2 in modo che rappresenti una riga).Ma ho bisogno di in qualche modo capire quali linee erano su un'estremità della linea intersecata, e quali linee erano dall'altra parte della linea intersecata ...

Questo è un po 'come l'opposto di un metodo di combinazione della geometria, qualcosa come una geometria divide metodo che sto cercando di mettere insieme.

Qualche idea?

Grazie!

È stato utile?

Soluzione

Beh, è stato divertente, ecco cosa ho fatto (onestamente non ho idea se questo è il modo "giusto" di se c'è un modo più efficiente).

    .
  1. Creare una trasformata che sposta la geometria in modo che la linea divisoria sia sull'asse y.
  2. Per ogni riga nella geometria - se x <0 è a sinistra, se x> 0 è sulla destra, se la linea attraversa l'asse y dividelo in due linee.
  3. trasforma entrambe le liste di linee usando l'inverso della trasformazione dal punto 1 e ricostrui una geometria da loro.
  4. Ecco un metodo di Splitgeometry che prende una geometria e una linea definita da due punti e restituisce le due geometrie:

        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);
            }
        }
    
    .

Altri suggerimenti

Il modo per capire quali linee sono su quale lato della linea di intersezione è quella di calcolare il segno del determinante degli endpoint della linea relativi alla linea di intersezione.Positivo è un lato, negativo è l'altro.

Se si desidera avere un intersezione più sofisticato, per esempio, all'interno di un segmento di linea, è necessario creare un grafico di bordi e vertici doppiamente diretti e calcolare l'intersezione della linea intersezione e ciascun bordo del poligono.Quindi inserire i vertici in cui la linea si interseca i bordi e ritrae il grafico, costruendo un poligono dai bordi diretti mentre si seguono l'uno dall'altra.

Se stai cercando un'implementazione di questo, controlla Net topology suite ,Il che, sebbene utilizzato principalmente per GIS, è utile anche per problemi generali di computazionale-geometria come questo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top