2009-08-11 7 views
1

Je veux dessiner un graphique normal avec quelques vertex et bords dans WPF 3D. Cela signifie que les sommets seront des sphères et que les arêtes seront des cylindres.Joindre deux sphères avec un cylindre dans WPF 3D

Je veux d'abord dessiner quelques-unes des sphères, puis les connecter avec des cylindres. Je suis capable de dessiner les sphères et les cylindres séparément dans un espace libre en utilisant les exemples dans le texte de programmation graphique WPF pratique. Je n'ai reçu aucune aide pour les rejoindre ensemble. Comment cela peut-il être fait?

+0

Je pense que vous voulez dire «sphères de – epotter

+1

Situ, quand vous dites "lances", voulez-vous dire comme « rond des balles"? Si c'est le cas, l'orthographe correcte est "sphères". Ou voulez-vous dire une flèche longue et épaisse (dans ce cas "lances" est correct)? –

+0

Merci andrew et potter vous avez raison les gars (Sphères). Désolé pour la confusion. – SituStarz

Répondre

5

Voici deux sphères, reliées par un cylindre, tournant dans un espace 3D. La méthode Init prend deux points, mais je crains que vous ne puissiez changer l'axe Z que si vous voulez que les sphères soient correctement connectées.

Le code est un peu un gâchis, compilé à partir d'un certain nombre de sources, y compris votre propre code de génération de sphère que vous avez publié dans une autre question.

XAML avec ViewPort:

<Window x:Class="wpfspin.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <Viewport3D Name="mainViewport" ClipToBounds="True" HorizontalAlignment="Stretch" Height="300"> 
      <Viewport3D.Camera> 
       <PerspectiveCamera 
        LookDirection="0,0,-20" 
        UpDirection="0,1,0" 
        Position="0,0,100" 
        /> 
      </Viewport3D.Camera> 
      <ModelVisual3D> 
       <ModelVisual3D.Content> 
        <Model3DGroup x:Name="group3d"> 

         <SpotLight Position="30,30,30" x:Name="mySpotLight" Color="Yellow" InnerConeAngle="100" OuterConeAngle="1000" Range="100" /> 
        </Model3DGroup> 
       </ModelVisual3D.Content> 
      </ModelVisual3D> 
     </Viewport3D> 
    </StackPanel> 
</Window> 

Et le code-behind:

using System; 
using System.Collections.Generic; 
using System.Timers; 
using System.Windows; 
using System.Windows.Media; 
using System.Windows.Media.Media3D; 
using System.Windows.Threading; 

namespace wpfspin 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      Init(new Point3D(0, 0, 30), new Point3D(0, 0, -30)); 
     } 

     private Timer _timer; 
     private readonly List<ModelVisual3D> _models = new List<ModelVisual3D>(); 
     private double _angle; 


     public void Init(Point3D firstPoint, Point3D secondPoint) 
     { 
      var midPoint = firstPoint - secondPoint; 

      _models.Add(CreateSphere(firstPoint, 10, 10, 10, Colors.AliceBlue)); 
      _models.Add(CreateSphere(secondPoint, 10, 10, 10, Colors.AliceBlue)); 
      _models.Add(GetCylinder(GetSurfaceMaterial(Colors.Red), secondPoint, 2, midPoint.Z)); 

      _models.ForEach(x => mainViewport.Children.Add(x)); 
      _timer = new Timer(10); 
      _timer.Elapsed += TimerElapsed; 
      _timer.Enabled = true; 
     } 


     void TimerElapsed(object sender, ElapsedEventArgs e) 
     { 
      Dispatcher.Invoke(DispatcherPriority.Normal, new Action<double>(Transform), 0.5d); 
     } 


     public MaterialGroup GetSurfaceMaterial(Color colour) 
     { 
      var materialGroup = new MaterialGroup(); 
      var emmMat = new EmissiveMaterial(new SolidColorBrush(colour)); 
      materialGroup.Children.Add(emmMat); 
      materialGroup.Children.Add(new DiffuseMaterial(new SolidColorBrush(colour))); 
      var specMat = new SpecularMaterial(new SolidColorBrush(Colors.White), 30); 
      materialGroup.Children.Add(specMat); 
      return materialGroup; 
     } 


     public ModelVisual3D GetCube(MaterialGroup materialGroup, Point3D point, Size3D size) 
     { 
      var farPoint = new Point3D(point.X - (size.X/2), point.Y - (size.Y/2), point.Z - (size.Z/2)); 
      var nearPoint = new Point3D(point.X + (size.X/2), point.Y + (size.Y/2), point.Z + (size.Z/2)); 

      var cube = new Model3DGroup(); 
      var p0 = new Point3D(farPoint.X, farPoint.Y, farPoint.Z); 
      var p1 = new Point3D(nearPoint.X, farPoint.Y, farPoint.Z); 
      var p2 = new Point3D(nearPoint.X, farPoint.Y, nearPoint.Z); 
      var p3 = new Point3D(farPoint.X, farPoint.Y, nearPoint.Z); 
      var p4 = new Point3D(farPoint.X, nearPoint.Y, farPoint.Z); 
      var p5 = new Point3D(nearPoint.X, nearPoint.Y, farPoint.Z); 
      var p6 = new Point3D(nearPoint.X, nearPoint.Y, nearPoint.Z); 
      var p7 = new Point3D(farPoint.X, nearPoint.Y, nearPoint.Z); 
      //front side triangles 
      cube.Children.Add(CreateTriangleModel(materialGroup, p3, p2, p6)); 
      cube.Children.Add(CreateTriangleModel(materialGroup, p3, p6, p7)); 
      //right side triangles 
      cube.Children.Add(CreateTriangleModel(materialGroup, p2, p1, p5)); 
      cube.Children.Add(CreateTriangleModel(materialGroup, p2, p5, p6)); 
      //back side triangles 
      cube.Children.Add(CreateTriangleModel(materialGroup, p1, p0, p4)); 
      cube.Children.Add(CreateTriangleModel(materialGroup, p1, p4, p5)); 
      //left side triangles 
      cube.Children.Add(CreateTriangleModel(materialGroup, p0, p3, p7)); 
      cube.Children.Add(CreateTriangleModel(materialGroup, p0, p7, p4)); 
      //top side triangles 
      cube.Children.Add(CreateTriangleModel(materialGroup, p7, p6, p5)); 
      cube.Children.Add(CreateTriangleModel(materialGroup, p7, p5, p4)); 
      //bottom side triangles 
      cube.Children.Add(CreateTriangleModel(materialGroup, p2, p3, p0)); 
      cube.Children.Add(CreateTriangleModel(materialGroup, p2, p0, p1)); 
      var model = new ModelVisual3D(); 
      model.Content = cube; 
      return model; 
     } 


     private Model3DGroup CreateTriangleModel(MaterialGroup materialGroup, Triangle triangle) 
     { 
      return CreateTriangleModel(materialGroup, triangle.P0, triangle.P1, triangle.P2); 
     } 


     private Model3DGroup CreateTriangleModel(Material material, Point3D p0, Point3D p1, Point3D p2) 
     { 
      var mesh = new MeshGeometry3D(); 
      mesh.Positions.Add(p0); 
      mesh.Positions.Add(p1); 
      mesh.Positions.Add(p2); 
      mesh.TriangleIndices.Add(0); 
      mesh.TriangleIndices.Add(1); 
      mesh.TriangleIndices.Add(2); 
      var normal = CalculateNormal(p0, p1, p2); 
      mesh.Normals.Add(normal); 
      mesh.Normals.Add(normal); 
      mesh.Normals.Add(normal); 

      var model = new GeometryModel3D(mesh, material); 

      var group = new Model3DGroup(); 
      group.Children.Add(model); 
      return group; 
     } 


     private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2) 
     { 
      var v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); 
      var v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); 
      return Vector3D.CrossProduct(v0, v1); 
     } 


     void Transform(double adjustBy) 
     { 
      _angle += adjustBy; 

      var rotateTransform3D = new RotateTransform3D { CenterX = 0, CenterZ = 0 }; 
      var axisAngleRotation3D = new AxisAngleRotation3D { Axis = new Vector3D(1, 1, 1), Angle = _angle }; 
      rotateTransform3D.Rotation = axisAngleRotation3D; 
      var myTransform3DGroup = new Transform3DGroup(); 
      myTransform3DGroup.Children.Add(rotateTransform3D); 
      _models.ForEach(x => x.Transform = myTransform3DGroup); 
     } 


     public ModelVisual3D GetCylinder(MaterialGroup materialGroup, Point3D midPoint, double radius, double depth) 
     { 
      var cylinder = new Model3DGroup(); 
      var nearCircle = new CircleAssitor(); 
      var farCircle = new CircleAssitor(); 

      var twoPi = Math.PI * 2; 
      var firstPass = true; 

      double x; 
      double y; 

      var increment = 0.1d; 
      for (double i = 0; i < twoPi + increment; i = i + increment) 
      { 
       x = (radius * Math.Cos(i)); 
       y = (-radius * Math.Sin(i)); 

       farCircle.CurrentTriangle.P0 = midPoint; 
       farCircle.CurrentTriangle.P1 = farCircle.LastPoint; 
       farCircle.CurrentTriangle.P2 = new Point3D(x + midPoint.X, y + midPoint.Y, midPoint.Z); 

       nearCircle.CurrentTriangle = farCircle.CurrentTriangle.Clone(depth, true); 

       if (!firstPass) 
       { 
        cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle)); 
        cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle)); 

        cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle.P2, farCircle.CurrentTriangle.P1, nearCircle.CurrentTriangle.P2)); 
        cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle.P2, nearCircle.CurrentTriangle.P1, farCircle.CurrentTriangle.P2)); 
       } 
       else 
       { 
        farCircle.FirstPoint = farCircle.CurrentTriangle.P1; 
        nearCircle.FirstPoint = nearCircle.CurrentTriangle.P1; 
        firstPass = false; 
       } 
       farCircle.LastPoint = farCircle.CurrentTriangle.P2; 
       nearCircle.LastPoint = nearCircle.CurrentTriangle.P2; 
      } 
      var model = new ModelVisual3D { Content = cylinder }; 
      return model; 
     } 


     public ModelVisual3D CreateSphere(Point3D center, double radius, int u, int v, Color color) 
     { 
      Model3DGroup spear = new Model3DGroup(); 

      if (u < 2 || v < 2) 
       return null; 
      Point3D[,] pts = new Point3D[u, v]; 
      for (int i = 0; i < u; i++) 
      { 
       for (int j = 0; j < v; j++) 
       { 
        pts[i, j] = GetPosition(radius, 
        i * 180/(u - 1), j * 360/(v - 1)); 
        pts[i, j] += (Vector3D)center; 
       } 
      } 

      Point3D[] p = new Point3D[4]; 
      for (int i = 0; i < u - 1; i++) 
      { 
       for (int j = 0; j < v - 1; j++) 
       { 
        p[0] = pts[i, j]; 
        p[1] = pts[i + 1, j]; 
        p[2] = pts[i + 1, j + 1]; 
        p[3] = pts[i, j + 1]; 
        spear.Children.Add(CreateTriangleFace(p[0], p[1], p[2], color)); 
        spear.Children.Add(CreateTriangleFace(p[2], p[3], p[0], color)); 
       } 
      } 
      ModelVisual3D model = new ModelVisual3D(); 
      model.Content = spear; 
      return model; 
     } 


     private Point3D GetPosition(double radius, double theta, double phi) 
     { 
      Point3D pt = new Point3D(); 
      double snt = Math.Sin(theta * Math.PI/180); 
      double cnt = Math.Cos(theta * Math.PI/180); 
      double snp = Math.Sin(phi * Math.PI/180); 
      double cnp = Math.Cos(phi * Math.PI/180); 
      pt.X = radius * snt * cnp; 
      pt.Y = radius * cnt; 
      pt.Z = -radius * snt * snp; 
      return pt; 
     } 


     public Model3DGroup CreateTriangleFace(Point3D p0, Point3D p1, Point3D p2, Color color) 
     { 
      MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); 

      Vector3D normal = VectorHelper.CalcNormal(p0, p1, p2); 
      mesh.Normals.Add(normal); 
      mesh.Normals.Add(normal); 
      mesh.Normals.Add(normal); 

      Material material = new DiffuseMaterial(
       new SolidColorBrush(color)); 
      GeometryModel3D model = new GeometryModel3D(
       mesh, material); 
      Model3DGroup group = new Model3DGroup(); 
      group.Children.Add(model); 
      return group; 
     } 


     private class VectorHelper 
     { 
      public static Vector3D CalcNormal(Point3D p0, Point3D p1, Point3D p2) 
      { 
       Vector3D v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); 
       Vector3D v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); 
       return Vector3D.CrossProduct(v0, v1); 
      } 
     } 
    } 

    public class CircleAssitor 
    { 
     public CircleAssitor() 
     { 
      CurrentTriangle = new Triangle(); 
     } 

     public Point3D FirstPoint { get; set; } 
     public Point3D LastPoint { get; set; } 
     public Triangle CurrentTriangle { get; set; } 
    } 

    public class Triangle 
    { 
     public Point3D P0 { get; set; } 
     public Point3D P1 { get; set; } 
     public Point3D P2 { get; set; } 

     public Triangle Clone(double z, bool switchP1andP2) 
     { 
      var newTriangle = new Triangle(); 
      newTriangle.P0 = GetPointAdjustedBy(this.P0, new Point3D(0, 0, z)); 

      var point1 = GetPointAdjustedBy(this.P1, new Point3D(0, 0, z)); 
      var point2 = GetPointAdjustedBy(this.P2, new Point3D(0, 0, z)); 

      if (!switchP1andP2) 
      { 
       newTriangle.P1 = point1; 
       newTriangle.P2 = point2; 
      } 
      else 
      { 
       newTriangle.P1 = point2; 
       newTriangle.P2 = point1; 
      } 
      return newTriangle; 
     } 

     private Point3D GetPointAdjustedBy(Point3D point, Point3D adjustBy) 
     { 
      var newPoint = new Point3D { X = point.X, Y = point.Y, Z = point.Z }; 
      newPoint.Offset(adjustBy.X, adjustBy.Y, adjustBy.Z); 
      return newPoint; 
     } 
    } 
} 
Questions connexes