Nasıl görsel 2 çemberleri bağlamak için?

oy
1

Biz 2 daire' x ve y merkezi konumunu bilmek ve yarıçapı aynıdır. Ben görsel olarak 2 çemberin merkezidir bağlamak hangi hat üzerinde her nokta için beraberlik elips olmadan döngü çevreleri bağlamak istiyorum.

Bundan:

Buna:

Kod:

int radius = 75;

int x1 = 100;
int y1 = 200;

int x2 = 300;
int y2 = 100;

g.FillEllipse(Brushes.Blue, new Rectangle(x1 - radius / 2, y1 - radius / 2, radius, radius));
g.FillEllipse(Brushes.Blue, new Rectangle(x2 - radius / 2, y2 - radius / 2, radius, radius));
Oluştur 20/10/2018 saat 14:04
kaynak kullanıcı
Diğer dillerde...                            


3 cevaplar

oy
6

Daireler aynı Çap olmadığı zamanlarda için bir çözüm.

Gerekli ilk bilgiler iki çemberlerinin merkezleri arasındaki mesafedir.
Bunu hesaplamak için kullandığımız Öklid mesafe bir Kartezyen düzlemde uygulanan:

Öklit uzaklık

Nerede (x1, y1)ve (x2, y2)iki Circles Merkezleri koordinatlardır.
Hesaplanan: Biz de (pozitif veya negatif değer olarak ifade edilir) Yönü bilmek gerekir [Distance]her zaman pozitif olacaktır.

içinde C#o, o kadar kodlanabilir:

float Direction = (Circle1Center.X > Circle2Center.X) ? -1 : 1;
float Distance = (float)Math.Sqrt(Math.Pow(Circle1Center.X - Circle2Center.X, 2) + 
                                  Math.Pow(Circle1Center.Y - Circle2Center.Y, 2));
Distance *= Direction;

Şimdi, biz de bir yön ifade iki Circles Merkezleri arasındaki mesafe var.
İki Merkezleri bağlayan - - bizim çizim düzlemine göre döndürüldüğünde Ayrıca bu sanal çizgi bilmemiz gerekir. Aşağıdaki şekilde, uzaklık bir hipotenüsünün olarak görülebilir dik üçgen h = (A, B) . CAçılı düz çizgilerin kesişme belirlenir, çemberlerin merkezleri çapraz eksene paralel uzanmaktadır.

Biz açısını Teta hesaplamak gerekir (θ).
Kullanılması Pisagor teoremi , biz açının Sine Teta olduğunu türetebilirsiniz Sinθ = b/h(şekildeki gibi)

Dik Üçgensinüs Kosinüs

Circles' Merkezleri koordinatlarını kullanarak, bu kodlanabilir C#olarak:
( Distanceüçgenin hipotenüsüdür)

float SinTheta = (Math.Max(Circle1Center.Y, Circle2Center.Y) - 
                  Math.Min(Circle1Center.Y, Circle2Center.Y)) / Distance;

SinThetabir açıyı ifade Radians. Biz ifade açıya ihtiyacım Degrees: GraphicsNesne dünya dönüşüm işlevleri için bu önlemi kullanır.

float RotationAngle = (float)(Math.Asin(SinTheta) * (180 / Math.PI));

Şimdi, bir oluşturmamız gerekir Connector , 2 Çevreler'i bağlayan bir şekle. Bir Çokgeninizi ihtiyacımız; Bir Dikdörtgen tarafın farklı çiftleri (biz farklı çaplarda Çevreler'i düşünen) olamaz.
Bu Poligon Circles Merkezleri, kısa kenarları = Çevreler'e Çapları arasındaki mesafesi = daha uzun tarafı olacaktır.

Bir Poligon katkıda bulunabilmek için, hem de kullanabilirsiniz Graphics.DrawPolygon ve GraphicsPath.AddPolygon . Ben seçiyorum GraphicsPathbir nedeni, yöntemin GraphicsPathdaha o tek şekil tutabilir ve bu şekiller yapabilirsiniz etkileşim , bir bakıma.

To bağlamak bir Poligon ile 2 düşünülen Çevreler'i, kullandığımız Poligon döndürmek gerekir RotationAngleönceden hesaplanmış.
Döndürmeyi gerçekleştirmek için basit bir yolu, dünyanın kullanarak, Circles birinin Merkezine koordinatları taşımaktır Graphics.TranslateTransform sonra kullanarak, yeni koordinatları döndürmek yöntemi Graphics.RotateTransform .

koordinatları dönüşümün merkezi dairenin çapına tekabül eden - - cirle merkezinde bizim Poligon konumlandırma kısa kenarlarından biri çizmek gerekir. rotasyon uygulanacağı zaman Dolayısıyla, bunun Merkezi'ne demirlemiş bu dönüşümün ortasında olacak kısa tarafı.

Burada, figure 3Çokgen (sarı şekli) (tamam, aldırma, bir dikdörtgen gibi görünüyor) yerlerini gösterir;
olarak figure 4döndürüldükten sonra aynı çokgen.

Merkezleme ve Çokgeninizi Döner

Notlar:
As Taw işaret , bu çizim tür hayal kırıklığı bir şeffaf olmayan Renk, bir SolidBrush kullanılarak yapılması gerekmektedir.
Eh, yarı saydam Fırça yasak değildir, ancak örtüşen şekiller farklı bir renk, olacak toplamı kavşak şeffaf renklerin.

Kullanarak, bir renk değişikliği olmadan yarı saydam bir Brush kullanarak şekiller çizmek için ancak mümkündür GraphicsPathtüm örtüşen parçalara uygulanan bir renk kullanarak şekiller doldurmak için yeteneği. Biz sadece varsayılan değiştirmeniz gerekir FillMode o ayarını, (Dokümanlar örneğe bakın) FillMode.Winding.

Örnek kod:
Bu örnekte, çevrelerin iki çift, bir Grafik bağlamında çizilir. Daha sonra bir Poligon şekli ile bağlanır, kullanılarak oluşturulan GraphicsPath.AddPolygon().
(Elbette, kullanmaya gerek Paintburada, bir çizilebilir Kontrol olayı Form)

Aşırı yardımcı fonksiyon kabul her iki dairenin merkezleri konumu, bir olarak ifade edilen PointFve bir RectangleFDaireler sınırları temsil yapı.

Bu, tam Renkler ve yarı saydam bir fırça kullanılarak, görsel neticedir:

Çizilen şekiller Görsel sonuç

using System.Drawing;
using System.Drawing.Drawing2D;

private float Radius1 = 30f;
private float Radius2 = 50f;

private PointF Circle1Center = new PointF(220, 47);
private PointF Circle2Center = new PointF(72, 254);
private PointF Circle3Center = new PointF(52, 58);
private PointF Circle4Center = new PointF(217, 232);


private void form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.CompositingQuality =  CompositingQuality.GammaCorrected;
    e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

    DrawLinkedCircles(Circle1Center, Circle2Center, Radius1, Radius2, Color.FromArgb(200, Color.YellowGreen), e.Graphics);
    DrawLinkedCircles(Circle3Center, Circle4Center, Radius1, Radius2, Color.FromArgb(200, Color.SteelBlue), e.Graphics);

    //OR, passing a RectangleF structure
    //RectangleF Circle1 = new RectangleF(Circle1Center.X - Radius1, Circle1Center.Y - Radius1, Radius1 * 2, Radius1 * 2);
    //RectangleF Circle2 = new RectangleF(Circle2Center.X - Radius2, Circle2Center.Y - Radius2, Radius2 * 2, Radius2 * 2);

    //DrawLinkedCircles(Circle1, Circle2, Color.FromArgb(200, Color.YellowGreen), e.Graphics);
}

Yardımcı fonksiyon:

public void DrawLinkedCircles(RectangleF Circle1, RectangleF Circle2, Color FillColor, Graphics g)
{
    PointF Circle1Center = new PointF(Circle1.X + (Circle1.Width / 2), Circle1.Y + (Circle1.Height / 2));
    PointF Circle2Center = new PointF(Circle2.X + (Circle2.Width / 2), Circle2.Y + (Circle2.Height / 2));
    DrawLinkedCircles(Circle1Center, Circle2Center, Circle1.Width / 2, Circle2.Width / 2, FillColor, g);
}

public void DrawLinkedCircles(PointF Circle1Center, PointF Circle2Center, float Circle1Radius, float Circle2Radius, Color FillColor, Graphics g)
{
    float Direction = (Circle1Center.X > Circle2Center.X) ? -1 : 1;
    float Distance = (float)Math.Sqrt(Math.Pow(Circle1Center.X - Circle2Center.X, 2) +
                                      Math.Pow(Circle1Center.Y - Circle2Center.Y, 2));
    Distance *= Direction;

    float SinTheta = (Math.Max(Circle1Center.Y, Circle2Center.Y) -
                      Math.Min(Circle1Center.Y, Circle2Center.Y)) / Distance;

    float RotationDirection = (Circle1Center.Y > Circle2Center.Y) ? -1 : 1;
    float RotationAngle = (float)(Math.Asin(SinTheta) * (180 / Math.PI)) * RotationDirection;

    using (GraphicsPath path = new GraphicsPath(FillMode.Winding))
    {
        path.AddEllipse(new RectangleF(-Circle1Radius, -Circle1Radius, 2 * Circle1Radius, 2 * Circle1Radius));
        path.AddEllipse(new RectangleF(-Circle2Radius + (Math.Abs(Distance) * Direction),
                                       -Circle2Radius, 2 * Circle2Radius, 2 * Circle2Radius));
        path.AddPolygon(new[] {
            new PointF(0, -Circle1Radius),
            new PointF(0, Circle1Radius),
            new PointF(Distance, Circle2Radius),
            new PointF(Distance, -Circle2Radius),
        });
        path.AddEllipse(new RectangleF(-Circle1Radius, -Circle1Radius, 2 * Circle1Radius, 2 * Circle1Radius));
        path.AddEllipse(new RectangleF(-Circle2Radius + (Math.Abs(Distance) * Direction),
                                       -Circle2Radius, 2 * Circle2Radius, 2 * Circle2Radius));

        path.CloseAllFigures();

        g.TranslateTransform(Circle1Center.X, Circle1Center.Y);
        g.RotateTransform(RotationAngle);

        using (SolidBrush FillBrush = new SolidBrush(FillColor)) {
            g.FillPath(FillBrush, path);
        }
        g.ResetTransform();
    }
}
Cevap 22/10/2018 saat 01:41
kaynak kullanıcı

oy
5

Diğer cevaplar şu ana kadar olduğu gibi hafifçe doğru çözüm özledim burada iki bağlayan biridir eşit büyüklükte çevreleri :

using (Pen pen = new Pen(Color.Blue, radius)
 { EndCap = LineCap.Round, StartCap = LineCap.Round }  )
     g.DrawLine(pen, x1, y1, x2, y2);

Burada görüntü açıklama girin

Notlar:

  • Genellikle is grafiklerin yumuşatma modu karşıtı takma itiraz ayarlamak iyi bir fikirdir ..

  • Dört dış hesaplamak için bazı matematik alacak farklı boyutlarda iki çemberleri bağlamak için teğet noktaları . Gerekli bir sinyal verebilen eğer Bunlardan biri, bir çokgen doldurmak için alabilir veya GraphicsPathdoldurmak için renk alfa <1 sahiptir durumda.

  • Jimi yorumları, GDI + dönüşüm kapasitesini kullanır Başka bir çözüme etmektedir.

  • Cevap veya yorum kısmı, bir şekilde arzu edilen şekle bakınız oval . Oval herhangi düz çizgiler olmaz olarak geometri kitapları bahsedilmektedir özellikle burada ortak konuşmada, bu tamam da, bu, yanlıştır.

  • Jimi belirtildiği gibi, ne isim yarıçap gerçekten çap çevrelerin. Ben kodunda yanlış bir terim bıraktı ama yapmamalısın !

Cevap 21/10/2018 saat 14:20
kaynak kullanıcı

oy
0

Sözde stili:

  circle1x;
    circle1y;

circle2x;
circle2y;


midx=circle1x-circle2x;
midy=circle2x-circle2x;

draw circle at midx midy;

Her iki yönde de, midx Midy için tekrarlayın. Başka bir daire ekleyin. dürüst adam, pürüzsüz yapmak için buna değer bu isnt, birkaç çevrelerin gerekir. Eğer oval iki merkezleri gibi her iki dairenin merkezini kullanarak bir oval çizmek gerekiyor

Cevap 20/10/2018 saat 14:34
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more