myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: WPF und XAML » Teilkreis über Vollkreis zeichnen?
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Teilkreis über Vollkreis zeichnen?

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
7.e.Q 7.e.Q ist männlich
myCSharp.de-Mitglied

avatar-3402.jpg


Dabei seit: 06.10.2004
Beiträge: 925
Entwicklungsumgebung: Visual Studio .NET 2010
Herkunft: Scheeßel


7.e.Q ist offline Füge 7.e.Q Deiner Kontaktliste hinzu

Teilkreis über Vollkreis zeichnen?

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hi Leute,

ich möchte gern über eine vorhandene Ellipse (Shape) eine weitere zeichnen, die die gleichen Eigenschaften bezüglich Geometrie besitzt, außer dass sie nur einen bestimmtes Bogenmaß abdeckt. Es soll also sowas wie ein ArcSegment werden.

Allerdings ist mir ArcSegment viel zu kompliziert umgesetzt, als dass ich damit in diesem speziellen Fall irgendwas produktives in brauchbarer Zeit umgesetzt bekäme.

Die (ich nenn's mal) "Teilellipse" sollte möglichst rein in XAML umgesetz sein, mit Binding an ein Objekt das einfach Anfangs und Endwinkel vorgibt.

Hat jemand eine Idee, wie man das realisieren könnte? "Einfach nur" eine Teilellipse zeichnen?

Danke

Grüße,
Hendrik
Neuer Beitrag 18.07.2011 17:49 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.453
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Es gibt dafür meiner Meinung nach keine fertigen Lösungen, aber wen du selbst soetwas umsetzen willst, und nicht weißt, wie es geht, kann ich dir diesen Artikel von Charles Petzold empfehlen:  Mathematics of ArcSegment
Neuer Beitrag 19.07.2011 10:48 Beiträge des Benutzers | zu Buddylist hinzufügen
7.e.Q 7.e.Q ist männlich
myCSharp.de-Mitglied

avatar-3402.jpg


Dabei seit: 06.10.2004
Beiträge: 925
Entwicklungsumgebung: Visual Studio .NET 2010
Herkunft: Scheeßel

Themenstarter Thema begonnen von 7.e.Q

7.e.Q ist offline Füge 7.e.Q Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja, den hab ich schon überflogen, werde da aber nicht so recht schlau draus.

Ich brech mir hier echt einen ab. Es kann doch nicht so schwer sein, nur einen Teil einer Ellipse unter Angabe eines Mittelpunktes (X, Y), zweier Radien (X, Y) und zweier Winkel (Anfang, Ende) zu zeichnen. Das ist doch kein besonderes Anliegen, oder?
Neuer Beitrag 19.07.2011 16:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.453
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Offenbar schon, sonst hätte sich Charles Petzold nicht die Mühe gemacht, so einen Artikel zu schreiben :)

Wahrscheinlich geht es wohl am einfachsten, wenn man die Bogensegmente als Bezier-Kurven darstellen kann. Man kann ja z.B. auch einen Kreis oder eine Ellipse sehr genau damit zeichnen.

Oder du verwendest einen GraphicPath, dann kannst du Ellipsen zeichnen und mit anderen Objekten kombinieren, bis dein Bogensegment bzw. Ellipsensegment übrig bleibt.

Vielleicht findet man auch eine Lösung, wenn du mal sagst, was du eigentlich darstellen möchtest. Wird es ein Tortendiagramm?
Neuer Beitrag 19.07.2011 17:14 Beiträge des Benutzers | zu Buddylist hinzufügen
7.e.Q 7.e.Q ist männlich
myCSharp.de-Mitglied

avatar-3402.jpg


Dabei seit: 06.10.2004
Beiträge: 925
Entwicklungsumgebung: Visual Studio .NET 2010
Herkunft: Scheeßel

Themenstarter Thema begonnen von 7.e.Q

7.e.Q ist offline Füge 7.e.Q Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Also der Sinn des ganzen ist folgender:

ich hab einem Freund zugesagt, ihm ein Programm zu schreiben, mit dem er schematisch die Muskulatur an Gliedmaßen von Insekten darstellen kann. Er hätte es gerne so, dass zwei oder mehr Elemente beispielsweise eines Wespenbeins in Vorderansicht als Kreise dargestellt werden. Als ob man direkt von vorn auf das ausgestreckte Bein schaut (grob, sehr schematisch halt). Der größere Kreis ist das aus der Perspektive hintere Glied des Beines, der jeweils kleinere Kreis das jeweils eine Ebene weiter vorne liegende Glied. Das sind die Vollkreise.

Die Teilkreise sollen nun Kontaktpunkte darstellen, an denen die Muskeln am Bein angewachsen sind. Es gehören also immer zwei Teilkreise zusammen. Einer auf einem weiter außen liegenden Vollkreis und einer auf einem weiter innen liegenden Vollkreis.

Und diese (schulligung, VERFLUCHTEN) Teilkreise zu zeichnen, bereitet mir gerade arge Kopfschmerzen.

Der Freund hat einfach keine Lust, für zig Proben immer und immer wieder die selben Bilder malen zu müssen. Da soll 'ne einfache Eingabemaske her, die ihm die Darstellung aus vorhandenen Daten erzeugt, bzw. wo er einfach klicken kann.

Und da ich das ganze nun so haben möchte, dass alle Elemente der Darstellung auswähl- und änderbare Objekte sind, versuche ich das so weit es eben geht in WPF und XAML zu programmieren. Grafische Darstellung und Daten sollen eben so weit es geht von einander getrennt bleiben.
Neuer Beitrag 19.07.2011 19:06 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.453
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Aha, also ein Insekten-Simulator...

Zitat von 7.e.Q:
Die Teilkreise sollen nun Kontaktpunkte darstellen, an denen die Muskeln am Bein angewachsen sind. Es gehören also immer zwei Teilkreise zusammen. Einer auf einem weiter außen liegenden Vollkreis und einer auf einem weiter innen liegenden Vollkreis.

Puh, naja, oder anders gefragt: Was genau muß an den Teilkreisen alles parametrisch einstellbar sein?

Es gibt im Prinzip zwei Herangehensweisen:
- Entweder zeichnest du dir einen oder mehrere Teilkreise in einem Zeichenprogramm. Die Kurven kannst du dann in XAML exportieren und beliebig transformieren, um die Insektenbeine zu zeichnen.
- Oder du verwendest die  CombinedGeometry-Klasse, um beliebige Formen aus Ellipsen und Dreiecken zu erstellen.
Neuer Beitrag 19.07.2011 21:13 Beiträge des Benutzers | zu Buddylist hinzufügen
7.e.Q 7.e.Q ist männlich
myCSharp.de-Mitglied

avatar-3402.jpg


Dabei seit: 06.10.2004
Beiträge: 925
Entwicklungsumgebung: Visual Studio .NET 2010
Herkunft: Scheeßel

Themenstarter Thema begonnen von 7.e.Q

7.e.Q ist offline Füge 7.e.Q Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ein Insektensimulator. :D Fast.

Einstellbar sein sollen "nur" Anfangs- und Endwinkel in einem polaren Koordinatensystem nach mathematischem Standard (pos. X als Cosinus des Winkels, pos. Y als Sinus des Winkels), dessen Ursprung im Mittelpunkt der Vollkreise liegt. Eventuell noch so Sachen wie Farbe und Breite des Strichs.

//edit 1
achso: der Radius des Kreises (bzw. beide Radien) ergibt sich aus dem zugeordneten Glied. Das ist also auch quasi eine einstellbare Größe. Ich zieh das als hierarchische Struktur auf: Körperteil -> Teilglied -> Kontaktpunkt, wobei jedes Körperteil mehrere Teilglieder und jedes Teilglied mehrere Kontaktpunkte haben kann.
//edit 1 ende

Die Winkel sollen veränderbar sein (möglichst genau). Am besten per Drag&Drop mit Thumbs an beiden Enden, wenn der jeweilige Kontaktpunkt ausgewählt ist. Auch einer der Gründe, wieso ich das alles mit den vorhandenen Komponenten aufzuziehen versuche und es nicht selber per OnRender zeichne. Die bieten schon einige dafür notwendige Funktionen.

CombinedGeometry... kann ich die auch so verwenden, dass das ein offener Pfad wird? Ich hab's schon versucht, die Teilkreise als Exclude zu erzeugen, indem ich ein "Rechteck" ausschneide, dem eine den Anfangs- und Endwinkeln entsprechende Ecke fehlt. Schwer zu erklären... jedenfalls hätte ich damit zwar einen passenden Kreisbogen bekommen; jedoch wäre dieser Teil eines geschlossenen Tortenstücks gewesen. Ich brauch aber wirklich NUR den Kreisbogen als offenen Pfad.

Is datt kompliziert...

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von 7.e.Q am 19.07.2011 22:49.

Neuer Beitrag 19.07.2011 22:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MrSparkle MrSparkle ist männlich
myCSharp.de-Team

avatar-2159.gif


Dabei seit: 16.05.2006
Beiträge: 5.453
Herkunft: Leipzig


MrSparkle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Mit CreateGeometry kannst du keine Pfade erstellen, soweit ich weiß, sondern nur geschlossene Formen.

Aber was spricht dagegen, einen Kreisbogen aus einem großen und einem bißchen kleineren Kreis zu erstellen (indem du den kleineren vom größeren abziehst) und dann mit einem Dreieck zu verschneiden (mit Intersection)?
Neuer Beitrag 20.07.2011 10:20 Beiträge des Benutzers | zu Buddylist hinzufügen
7.e.Q 7.e.Q ist männlich
myCSharp.de-Mitglied

avatar-3402.jpg


Dabei seit: 06.10.2004
Beiträge: 925
Entwicklungsumgebung: Visual Studio .NET 2010
Herkunft: Scheeßel

Themenstarter Thema begonnen von 7.e.Q

7.e.Q ist offline Füge 7.e.Q Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Das könnte in der Tat funktionieren. Jedoch muss ich mir noch Gedanken machen, wie ich am besten die Verschneidung mit dem Dreieck realisiere, da es auch Kreisbögen geben kann, die mehr als 90° abdecken. Manche möglicherweise mehr als 180°. Da wird das dann mit dem Dreieck nix. Da müssten mehrere her... huah! Das wird ein Spaß... Da werde ich mit XAML alleine wohl nicht weit kommen, was?!
Neuer Beitrag 20.07.2011 16:43 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
7.e.Q 7.e.Q ist männlich
myCSharp.de-Mitglied

avatar-3402.jpg


Dabei seit: 06.10.2004
Beiträge: 925
Entwicklungsumgebung: Visual Studio .NET 2010
Herkunft: Scheeßel

Themenstarter Thema begonnen von 7.e.Q

7.e.Q ist offline Füge 7.e.Q Deiner Kontaktliste hinzu

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

So. Das Zeichnen des Teilkreises funktioniert jetzt:

Ich habe mir eine Custom Shape erzeugt, die über den Winkelbereich in 1° Schritten BezierSegments anlegt. Performance ist da erstmal Nebensache.

Nächstes Problem: (gelöst)

Die Shape verhält sich seltsam beim Verkleinern des Fensters. Statt dass sie stretched und mit dem Fenster zusammen kleiner wird, wird sie größer. Ich habe den Eindruck, das hängt damit zusammen, dass der Strich, der aus der PathGeometry gezeichnet wird, aufgrund seiner Dicke über den Rand des Renderbereichs hinaus steht.

Vielleicht mag sich ja mal "fix" jemand meine Custom Shape anschauen und mir sagen, was daran Bockmist ist. Ich vermute 'ne Menge. Das Ding ist jetzt mal quick'n'dirty zusammen geschustert.


//update: Problem gelöst. Nun folgende Variante tut ihren Dienst exakt so, wie ich es gerne hätte. Verbesserungsvorschläge werden natürlich trotzdem gerne angenommen.

C#-Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows;
using System.Windows.Data;
using System.Windows.Controls.Primitives;

namespace InsectJoint
{
    public class Arc : Shape
    {
        public double StartAngle
        {
            get { return (double)GetValue(StartAngleProperty); }
            set { SetValue(StartAngleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for StartAngle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StartAngleProperty =
            DependencyProperty.Register("StartAngle", typeof(double), typeof(Arc), new UIPropertyMetadata(0.0D));



        public double EndAngle
        {
            get { return (double)GetValue(EndAngleProperty); }
            set { SetValue(EndAngleProperty, value); }
        }

        // Using a DependencyProperty as the backing store for EndAngle.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty EndAngleProperty =
            DependencyProperty.Register("EndAngle", typeof(double), typeof(Arc), new UIPropertyMetadata(0.0D));

        public bool AngleInDegrees
        {
            get { return (bool)GetValue(AngleInDegreesProperty); }
            set { SetValue(AngleInDegreesProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AngleInDegrees.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AngleInDegreesProperty =
            DependencyProperty.Register("AngleInDegrees", typeof(bool), typeof(Arc), new UIPropertyMetadata(true));


        PathGeometry _geo = new PathGeometry();
        PathFigure _fig = new PathFigure();

        public Arc()
        {
            _fig.IsClosed = false;
            _geo.Figures.Add(_fig);
        }

        protected override Geometry DefiningGeometry
        {
            get
            {
                _fig.Segments.Clear();

                double start = StartAngle, end = EndAngle;
                if (AngleInDegrees)
                {
                    start *= (Math.PI / 180.0D);
                    end *= (Math.PI / 180.0D);
                }

                double step = 2.0D * (Math.PI / 180);

                _fig.StartPoint = calcPoint(start);

                for (double i = start + step; i <= end; i += (step * 3))
                {
                    Point p1 = calcPoint(i - step * 2);
                    Point p2 = calcPoint(i - step);
                    Point p3 = calcPoint(i);

                    BezierSegment seg = new BezierSegment();
                    seg.Point1 = p1;
                    seg.Point2 = p2;
                    seg.Point3 = p3;

                    _fig.Segments.Add(seg);
                }

                return _geo;
            }
        }

        private Point calcPoint(double angle)
        {
            Rect r = LayoutInformation.GetLayoutSlot(this);
            double offX = (r.Width / 2.0D);
            double offY = (r.Height / 2.0D);
            double radX = (r.Width / 2.0D);
            double radY = (r.Height / 2.0D);

            Point p = new Point();
            p.X = radX * Math.Cos(angle) + offX;
            p.Y = radY * -Math.Sin(angle) + offY;
            return p;
        }
    }
}

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von 7.e.Q am 22.07.2011 01:44.

Neuer Beitrag 22.07.2011 00:46 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegen mehr als 8 Jahre.
Bolle Bolle ist männlich
myCSharp.de-Mitglied

Dabei seit: 25.02.2020
Beiträge: 1
Entwicklungsumgebung: Visual Studio 2017
Herkunft: Zweibrücken / Deutschland


Bolle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Dieser Beitrag ist zwar schon sehr alt, aber ich möchte trotzdem gerne jedem helfen, der wie ich heute danach sucht und evtl. umständlich nach Lösungen sucht, die mit dem ArcSegment wunderbar zu handeln sind.
Meine Lösung im XAML wäre:

XML-Code:
            <Path Stroke="GreenYellow" StrokeThickness="4">
                <Path.Data>
                    <PathGeometry>
                        <PathGeometry.Figures>
                            <PathFigureCollection>
                                <PathFigure StartPoint="100,100">
                                    <PathFigure.Segments>
                                        <PathSegmentCollection>
                                            <LineSegment Point="{Binding ArcStartPoint}"/>
                                            <ArcSegment Size="50, 50" IsLargeArc="{Binding BogenUeber180Grad, Mode=OneWay}" SweepDirection="Clockwise" Point="{Binding ArcEndPoint}"/>
                                            <LineSegment Point="100,100"/>
                                        </PathSegmentCollection>
                                    </PathFigure.Segments>
                                </PathFigure>
                            </PathFigureCollection>
                        </PathGeometry.Figures>
                    </PathGeometry>
                </Path.Data>
            </Path>

Dabei habe ich für meine Bedürfnisse zusätzlich noch einen quasi Zeiger vom Mittelpunkt zum Startpunkt und zum Endpunkt eingebaut.

Es gibt bei dem ArcSegment hauptsächlich folgendes zu verstehen:
* Will man einen kompletten Kreis/Ellipse, darf der StartPoint nicht genau auf dem Point liegen.
* Beim Kreis in der Bildmitte, sollte man Size halb so groß setzen, wie den Durchmesser des gewünschten Kreises.
* IsLargeArc sollte wie hier mit dem Binding auf BogenUeber180Grad dann true sein, wenn der Winkel dazwischen>180° ist und false, wenn dieser kleiner 180° ist.

Die beiden Punkte ArcStartPoint und ArcEndPoint kann man sich mit den üblichen trigonometrischen Berechnungen, wie Cosinussatz und Bogenmass berechnen.
Für eine komplexe Simulation eines Insekts kann ich mir vorstellen, die Orientierung leicht zu verlieren, aber viel einfacher wird es wohl nicht werden.
Bei Ellipsen wird es zugegebenerweise etwas aufwendiger, aber die braucht man schematisch vielleicht auch nicht unbedingt.

Bolle hat dieses Bild (verkleinerte Version) angehängt:
ArcSegment.png
Volle Bildgröße

Neuer Beitrag 25.02.2020 17:25 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 9 Jahre.
Der letzte Beitrag ist älter als 6 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 21.09.2020 15:02