Click here to Skip to main content
Click here to Skip to main content

A 3D Plotting Library in C#

By , 9 Jun 2006
 
Prize winner in Competition "C# May 2006"

Screenshot

Introduction

This article presents a set of classes which allows you to draw pictures in a 3-dimensional coordinate space. Within this article, I'll touch on some of the mathematical concepts involved (it doesn't require anything more than what you learned in high school trigonometry), I'll explain the basics of how to use the library, and I'll list the resources I used in creating it.

Background

I recently became disturbingly obsessed with the motion of falling dominoes and the math that could describe it. I spent about two weeks scrawling calculations on the back of napkins and ATM receipts, and I covered the walls of my cubicle at work with increasingly refined problem descriptions and incomplete solutions. Once I had developed a working formula, I decided to implement it in code. This library is the end result of my attempt to animate a row of falling dominoes.

My domino calculations were based on relative positioning ("Turn right 45 degrees, then move forward 100 units") rather than absolute positioning ("Move to location [45, 12, 83]"). A language like LOGO is well suited to this kind of drawing, and my library has similar functionality. But because we're dealing in 3-dimensions, my library allows you to turn the cursor not only left and right, but also up (out of the screen, towards you) and down (into the screen, away from you).

Establishing Orientation

In order for the cursor to move around in 2-dimensions, it needs to be aware of both its location and its direction. Location can be established with a point [x,y], and we can establish direction with a vector. A vector establishes the cursor's forward direction, and is used to calculate the left and right directions.

In 3-dimensions, though, it's a bit trickier. The cursor's direction doesn't present us with all the information we need. Have a look at this example. Here are two airplanes, both flying in the same direction. Each airplane has a green guide pointing in the direction that it considers to be forward, a blue guide pointing towards what it considers to be right, and a purple guide pointing towards what it considers to be up.

Airplane Right-side-upAirplane Up-side-down

Both of these planes are headed in the same direction, but if you told them both to turn right, they'd each do something different. That's why it's not enough to establish a direction in 3-dimensions. When moving around in 3D, we need to establish an orientation. Luckily, this is pretty easy. All we need is one extra vector. In addition to a vector pointing towards what we consider to be forward, we'll also need one pointing towards what we consider to be up. Once we establish two directions, we can use them to calculate all the other directions.

Using the code

The first class you need to become familiar with is Plotter3D. The simplest constructor just takes a Graphics object. This can be any valid Graphics object, from a Form, a Bitmap, a Metafile, etc.

using (Graphics g = this.CreateGraphics())
{
    using (CPI.Plot3D.Plotter3D p = new CPI.Plot3D.Plotter3D(g))
    {
        // Do some stuff with the plotter here
    }
}

Once you've created a Plotter3D object, you can start drawing. Here's how you draw a square:

public void DrawSquare(Plotter3D p, float sideLength)
{
    for(int i = 0; i < 4; i++)
    {
        p.Forward(sideLength);  // Draw a line sideLength long
        p.TurnRight(90);        // Turn right 90 degrees
    }
}

In this function, p.Forward(sideLength) draws a side of the square, and p.TurnRight(90) turns right 90 degrees. If we repeat this sequence four times, we'll have drawn a square, and we'll end up back at our starting point. The function draws a square that looks like this:

Square

You can call the DrawSquare multiple times, to create a cube:

public void DrawCube(Plotter3D p, float sideLength)
{
    for (int i = 0; i < 4; i++)
    {
        DrawSquare(p, sideLength);
        p.Forward(sideLength);
        p.TurnDown(90);
    }
}

Notice that in this function, we call p.TurnDown(90). This turns the cursor in 3D so that it's moving away from you, into the computer screen. When we draw four squares at different locations, we end up with a cube that looks something like this:

Cube

Rotation

Once you've defined a shape, it's pretty easy to rotate it. That's one of the benefits of using relative coordinates instead of absolute coordinates. To draw a rotated shape, move the cursor to the point you want to use as the center of the rotation, turn the cursor left or right or up or down as much as you'd like, then retrace your steps back to the starting point, and draw your shape. An example will probably help. Let's rotate our square:

public void DrawRotatedSquare(Plotter3D p, float sideLength, float rotationAngle)
{
    // Since we don't want to draw while repositioning ourselves at the
    // center of the object, we'll lift the pen up
    p.PenUp();

    // Move to the center of the square
    p.Forward(sideLength / 2);
    p.TurnRight(90);
    p.Forward(sideLength / 2);
    p.TurnLeft(90);

    // Now we rotate as much as we want
    p.TurnRight(rotationAngle);

    // Now we retrace our steps to get back
    // to the (rotated) starting point
    p.TurnLeft(90);
    p.Forward(sideLength / 2);
    p.TurnLeft(90);
    p.Forward(sideLength / 2);
    p.TurnRight(180);

    // Put the pen back down, so we start drawing again
    p.PenDown();

    // Finally we draw the square as we normally would
    DrawSquare(p, sideLength);
}

So if we were to call:

DrawRotatedSquare(p, 50, 45);

we'd get something that looks like this:

Rotated Square

Using this technique, you can generate multiple images, each rotated a bit more than the last, to create animations like this:

Spinning Square

This rotation logic also works in 3D, so you can use it to rotate 3D objects however you like:

Spinning Cube 3

Perspective

When displaying 3D images on a 2D computer screen, we need to account for perspective. I shamelessly lifted my perspective logic from Paresh Solanki's excellent CodeProject article: A short discussion on mapping 3D objects to a 2D display. In my implementation, the "screen" is the plane formed by the X and Y axes, and the "camera" is a Point3D instance that you can specify in the constructor of a Plotter3D object. If you don't specify a camera position, it will default to the (completely arbitrary) location [-30, 0, -600]. Experiment with changing the camera position, and see how it affects your drawings.

Questions Which Will Probably Be Frequently Asked...

How do I draw a circle?

Short answer...you don't. You can only draw lines. Longer answer...you can fake it pretty convincingly by drawing a polygon with a lot of sides. Here's an example function which will draw an approximation of a circle with a specified diameter:

private void DrawCircle(Plotter3D p, float diameter)
{
    float radius = diameter / 2;

    // Increasing this number will create a better approximation,
    // but will require more work to draw
    int sides = 64;

    float innerAngle = 360F / sides;

    float sideLength = (float)(radius * 
      Math.Sin(Orientation3D.DegreesToRadians(innerAngle) / 2) * 2);

    // Save the initial position and orientation of the cursor
    Point3D initialLocation = p.Location;
    Orientation3D initialOrientation = p.Orientation.Clone();

    // Move to the starting point of the circle
    p.PenUp();
    p.Forward(radius - (sideLength / 2));
    p.PenDown();

    // Draw the circle
    for (int i = 0; i < sides; i++)
    {
        p.Forward(sideLength);
        p.TurnRight(innerAngle);
    }

    // Restore the position and orientation to what they were before
    // we drew the circle
    p.Location = initialLocation;
    p.Orientation = initialOrientation;
}

There are a couple of interesting things to notice about this function. First, it's actually drawing a polygon with 64 sides. If you increase the number of sides in the polygon, it'll draw a closer approximation of a circle, but you'll probably find that 64 is plenty in most cases.

You'll also notice that before we draw the circle, we save our location and orientation, and we restore it after we've drawn the circle. The reason for this is because this library does a lot of floating point math, and floating point math is imprecise. So even though we should end up back at our starting point after rotating 360 degrees, we can only really guarantee that we'll end up pretty close to the starting point. The errors caused by lack of precision are very small, but they could potentially add up after a while. So by saving our initial position and orientation beforehand, then restoring them afterwards, we can guarantee that our end point is exactly the same as our start point.

Finally, you'll notice that when saving the initial location, we simply call initialLocation = p.Location, but when saving the initial orientation, we call initialOrientation = p.Orientation.Clone(). We don't have to call Clone() on p.Location because p.Location is a Point3D, which is a value type, which means that initialLocation gets populated with a copy of the value. In contrast, p.Orientation is a reference type, which means that if we hadn't called Clone(), initialOrientation would have pointed to the same object as p.Orientation, which is not the behavior we want. The Clone() method creates a deep copy of the Orientation3D object.

Let's try the function out.

DrawCircle(p, 100);

draws a circle that looks like this:

Circle

I'd say that it looks pretty circular, all things considered. All of the rotation and animation stuff that we've learned so far also applies to this object, so we could, for example, draw a series of circles to create a sphere, and then rotate it around, like this:

Spinning Sphere

How do I draw a filled area?

You don't. You can only draw lines. As soon as you start doing anything fancier than lines, you need to start taking other things into account, like visibility determination, for example. That's beyond the scope of this project.

Why don't you mention Euler Angles, or Rotation Matrices, or Quaternions?

Because, all I really need this project to do is draw some lines in 3D, and that can be done entirely with vector arithmetic and some straightforward algebra and trigonometry. Of course, no discussion of 3D graphics is complete without mentioning a whole list of things that I haven't talked about, but this project isn't designed to be a complete 3D graphics package. This is just an easy-to-use method of visualizing and experimenting with 3D geometry. If you're looking for a high-powered, full-featured, 3D graphics library, have a look at DirectX or OpenGL.

So did you ever get around to animating dominoes, or what?

I sure did. The source code is included in the download, or you can look at the final result (exported to Flash) here.

Tips and Tricks

  • Whenever you design a new shape, try to abstract it into a separate function (like DrawCube, DrawSphere, etc.) rather than embedding the movements directly into your code. In some future revision, I'll probably create an abstract Shape class that can be built upon.
  • It's easy to lose your bearings while maneuvering the cursor around. Throughout the development cycle, I kept a toy airplane nearby and used it to keep track of the cursor's rotation. I encourage you to get a toy airplane as well, partly because it will help you visualize 3D movement, and partly because airplanes are awesome.

    Toy Airplane

About the Math

There's a lot of math under the covers here. That makes sense, given that this whole project started as an attempt to visualize a math problem that I'd been working on. Most of the math involves vectors in one way or another, and you'd do well to learn about vector arithmetic if you want to mess with the code. I learned everything I know about vector math from the book 3D Math Primer for Graphics and Game Development, which is a very good introduction to 3D math. The book gives a geometric interpretation for almost all of the math it presents, which really helps you to visualize just exactly what you're doing. I've included references to individual pages of the book in the code's XML comments.

About the Unit Tests

I've included a relatively large battery of NUnit tests with this project. Remember that floating-point arithmetic is complicated. There are about half-a-zillion different corner cases that will trip you up if you're not paying attention. Apart from having to deal with things like Infinity and NaN, it's relatively easy to perform an operation which gives you a tiny loss of precision, but which quickly multiplies into a very large loss of precision. The included tests check the results of a wide range of inputs. By and large, I've dealt with these concerns, so you don't have to worry very much if you're just using the library as is. If you're planning on extending this library, however, it would be a good idea to extend the unit tests accordingly.

References

History

  • June 7, 2006 - Initial posting.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Pete Everett
Software Developer (Senior)
United States United States
Member
Pete has just recently become a corporate sell-out, working for a wholly-owned subsidiary of "The Man". He counter-balances his soul-crushing professional life by practicing circus acrobatics and watching Phineas and Ferb reruns. Ducky Momo is his friend.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberkaliprasad12318 Apr '13 - 19:33 
superrrrrrrrrr
GeneralMy vote of 5memberMember 93723731 Feb '13 - 13:50 
Nothing but great straightforward examples, showing how to do no so simple things in C#/.Net. Thank you for sharing!
GeneralMy vote of 5membermanoj kumar choubey21 Feb '12 - 23:55 
Very Nice
GeneralMy vote of 5membertheanil25 Jan '12 - 9:46 
5
GeneralMy vote of 5memberNazmi Altun19 Dec '11 - 22:49 
Good job!
Generaldear Pete Everettmembereladyanai2214 May '10 - 23:26 
My name is Elad, I'm from Israel.
I am a student (CS) in the college of management.
I am using the project you build for my class presentation over 3rd party software.
I would like to show my classmates some kind of an API of your code.
and i saw that you wrote your notes inside the program in a special way.
is there any program i can run on your project that can create an API for me?
or do I need to do the hard work by hand?
Or maybe you do have an API somewhere out there?
 
thank you for your time!
regards,
Elad Yanai.
AnswerRe: dear Pete EverettmemberPete Everett15 May '10 - 1:57 
Hi, Elad,
 
I've never personally used it, but if you're trying to generate API documentation from XML comments, people seem to love NDoc.
 
http://ndoc.sourceforge.net/[^]
GeneralAwsomememberdedics11 Jun '09 - 3:42 
Hi,
thx for this great thing... i have no idea how to work with 3D objects, this is a great point to start from... thank you again!
Generalgreat, now we need a surfacememberpepepaco26 May '09 - 9:19 
it looks very nice, and simple, I wonder how can we use the same logic to translate for example, a perfect square into a trapezoid depending on perspective, plus, calculate the size of a shape depending on the "distance" relative to perspective over the square, and finally change the velocity as the same as the size, depending on the perspective...
 
could you please provide an advice to achieve this?.
 
regards.
GeneralRe: great, now we need a surfacememberMartijn van Dorp22 Jul '09 - 7:54 
Damn, I deleted the wrong post, now I have to write it again Frown | :( img src="/script/Forums/Images/smiley_smile.gif" align="top" alt="Smile | :)" />
 
Ill give some half pseudo code here:
 
//Initialize matrices:
Matrix world = //Identity, or any combination of translations, rotations and scaling.
Matrix view = Matrix.CreateLookAt(Vector3 cameraPosition, Vector3 targetPosition);
Matrix proj = Matrix.CreatePerspectiveFOV(Pi / 4, aspect ratio(width/height), near, far);
Matrix vp = new Matrix(
width,  0,       0,     0,
0,     -height,  0,     0,
0,      0,       1,     0,
width/2,height/2,0,     1);
//This matrix inverts the y axis, scales the point to the viewport, and translates the point to the middle of the viewport

//If you dont need to do lightning calculations you can combine all 4 of them.
Matrix worldView = world * view;
Matrix projVp = proj * vp;
 
//Actual transformation:
Vector4 point = new vector4(x,y,z,1);
point = Vector4.Transform(point, worldView);
//point is now in camera space, now you can calculate the lightning
//Normals should be transformed by the inverse transposed of worldView (Matrix.Transpose(Matrix.Invert(worldView));)
//Now you can preform lightning calculations, if you need psuedo code for that too just tell me.

point = Vector4.Transform(point, projVp);
point /= point.W;
//An now point is in (perspective) screen space :)
 
If want code where you just enter x,y,z and retrieve the screenspace coord as output just tell me and ill write it for you.
Or else you could try to write your own math library for it(It took me a while though, im 15 and I didin't know any linear algebra at all before I started creating my own 3D engine), Or if you wanna take it easy you could search the internet or use Xna/DirectX's math Smile | :)
 
Good luck
QuestionRotating the dominoesmemberrajesh kumar swain1 Jan '09 - 23:18 
Hello,
 
Its a great one!.
 
Can I rotate the dominoes to rotate in the similar manner as the cube does. Basically I need a cube to be placed within a dominoes and both rotate simultaneously on button click. The dominoes will rotate along with its axis along with the cube.
 
Any kind of help is appreciable.
 

Thanks,
Rajesh
GeneralI can not open itmemberthanhbinhbk0429 Aug '08 - 6:24 
I use C#2005, I even delete unit Test but It does not work.??? Can you help me? Point out exactly what I have to delete or Can you post a verified program?
GeneralRe: I can not open itmemberPete Everett3 Sep '08 - 9:56 
I don't know what to tell you, dude. I just downloaded, unzipped, opened, and built it, then ran the example program, and it all worked just fine.
 
What's the specific error that you're getting?
GeneralNice, but sooo slowmemberthany.org20 Jun '08 - 14:37 
How come drawing a simple object like the sphere is so incredibly slow? Do you have any idea what my GPU can do in a millisecond? This library does the same thing about a billion times slower. Therefor, I see much more potential in using XNA or MDX.
 
--
Thany

GeneralRe: Nice, but sooo slowmemberPete Everett21 Jun '08 - 7:02 
Well, yeah...
 
Dude, I hope you weren't planning on porting DOOM or anything. This project is a mathematical novelty, not a gaming framework.
 
All this thing can do is plot points in a 3D space, and draw lines to connect them. That's it, front-to-back. And when your library can only draw straight lines, a sphere is not a "simple object". It's an absurdly complex one.
 
In addition, it's built on top of the System.Drawing namespace. That's a fundamentally 2D environment. And all the 3D math that I'm doing is straight high school trigonometry using the System.Math class (no assembly optimizations, just straight managed code). It's simple, and it's illustrative, and it's turtle slow. And those were exactly the design goals of the project.
 
Anyway, I hope you're not too disappointed. Luckily, if you want to do some high-performance 3D stuff in an optimized framework, you've got about a thousand of them to choose from. Good luck.
GenerallicensememberPaul_e!16 May '08 - 8:57 
Dear Pete Everett,
 
I'm a student at the university college of Antwerp in Belgium.
Currently I'm doing research on balance measurement of CVA patients (people who had a stroke).
I'm using accelerometer sensors to monitor the position of their body. May I use part of your CPI3d code to make my life and the life of the CVA patients a little easier ? Smile | :) The software will be used for research only and will not be commercialized.
 
Best regards,
 
Paul
 
e_paul321@hotmail.com
 
--P.E.--

AnswerRe: licensememberPete Everett16 May '08 - 21:50 
Hi Paul,
 
I just officially assigned a Code Project Open License to the library, which roughly means that you're welcome to use it pretty much however you like. (Feel free to commercialize your software if you get the chance.)
 
Keep in mind, though, that I built the library as a proof-of-concept, and there are no guarantees that it actually works like it's supposed to in all the corner cases. So if you're planning to do anything serious with it, make sure you test it.
 
I hope it helps you out. Good luck with your research.
 
-Pete
QuestionHow open Plot3D_src ?memberyonnel27 Apr '08 - 7:54 
Hi,
 
Excuse for my english very bad.
 
I download Plot3D_src, but I can't open and use it.
 
How can I do ?
 
Thanks
AnswerRe: How open Plot3D_src ?memberPete Everett16 May '08 - 21:59 
Two possibilities come to mind. This is a Visual Studio 2005 solution, so if you're using an earlier version of visual studio, you won't be able to open it. Also, it uses the NUnit unit testing framework, so you won't be able to build the code without that.
 
If lack of NUnit is your problem, you can just remove the test project from the solution (you don't really need it) and everything else should build just fine. If you have an old version of Visual Studio, that's a little trickier. Here's a link[^] to a previous thread where someone converted the code to VS 2003.
 
Or if you're having still yet some other problem, you'll need to describe the environment you're working in a little better.
QuestionLocationmemberDyoXynE16 Apr '08 - 2:37 
Hi,
 
I want to say first that your article is really nice ! Easy to use and understand !
But ... I have a question about the location.
 
I changed the location because i wanted to have a good perspective.
But I don't know how draw the plot3D where I want.
 
For example, if I want to draw the same cube with : p.Location = new CPI.Plot3D.Point3D(50, 50, 500); at (0,0) of the Graphic.
I just want to do a kind of translation.
GeneralRe: LocationmemberPete Everett16 May '08 - 22:25 
If I'm reading your question correctly, you're trying to force the upper-left-hand corner of a cube at the virtual coords of (for example) [50,50,500] to be drawn at [0,0] of the Graphics object that we're projecting onto. If that's what you're trying to do, the library doesn't actually have any support for that. You can change the projected position of 3D objects by changing the camera location of the Plot3D, but that will also change the perspective, and therefore the look, of the projected objects.
 
Your best bet might be to draw your object onto a Bitmap, and when you're done drawing, pay attention to the BoundingBox property of the Plotter3D object. That'll tell you (approximately) what the 2D bounds are, and from there you can use regular ol' GDI+ calls to reposition the drawn image however you'd like.
 
Or if I've misunderstood your question, feel free to clarify.
 
(Sorry I took so long to respond. I didn't notice that anybody had posted a question. I probably accidentally deleted the e-mail notification.)
QuestionCan I Fill Shapesmembershiko_engin12 Feb '08 - 22:47 
Well done Pete,
Please can you tell me if i can use this work to fill the 3D shapes
with colors just like the cube?
AnswerRe: Can I Fill ShapesmemberPete Everett13 Feb '08 - 1:00 
Sorry. This is strictly a wireframe sort of thing. (That's actually one of the FAQs in the article.) Drawing filled areas in 3D is pretty hard, and I'm pretty lazy. If you want to do filled areas, you're better off with an actual 3D engine of some sort.
GeneralVery goodmemberharryrydz27 Jan '08 - 9:25 
Very well thought out and programmed. Well done!
QuestionHow to run???memberkhoa164198718 Nov '07 - 8:17 
Why I can't find NUnit namespace. Please tell me how can download that NUnit and put it in my project.
AnswerRe: How to run???memberPete Everett18 Nov '07 - 9:43 
NUnit is a unit testing framework which I used to develop the unit tests for the project. You can grab the framework from their web site at http://www.nunit.org/[^], or you can just remove the unit test project from the solution, and it'll build just fine for you.
GeneralRe: How to run???memberkhoa164198718 Nov '07 - 16:32 
By the way, can you tell me how download System.Window, System.Window.Media namespace. I don't know how to download it from microsoft site to import it to my project. Thanks a lot.
AnswerRe: How to run???memberPete Everett18 Nov '07 - 17:36 
That's pretty far off-topic, and you'll probably want to direct similar questions someplace (any place) else. System.Windows.Media seems to be a .NET 3.0 namespace. If you want to work with 3.0 with VS2005, you'll need to download the WPF extensions, which you can get here[^]. If you need any more help on the subject, try an appropriately themed forum.
GeneralFantastic Workmemberarvindhal31 Oct '07 - 4:50 
You've done an incredible job putting together this library and making it easy to use. I have a lot of programming experience (and my fair share of 2D/3D experience) but I've never seen such a targeted, light weight, flexible and easy to use library even from commercial offerings. Please keep up the good work. Just a thought, I haven't dug into your code but will this work one a windows mobile 2006 device?
GeneralRe: Fantastic WorkmemberPete Everett31 Oct '07 - 5:03 
Hi. Thanks for the comment. That's kind.
 
As far as windows mobile 2006, I've certainly never tried it, and I don't have a mobile device or emulator handy to test it out, but I can't think of any reason why it wouldn't work. The underlying code isn't really doing anything too fancy. Just some line-drawing methods from the Graphics class, and some basic trig functions from the Math class. so it should work just fine.
 
If you end up trying it out, leave a comment here if you think of it, letting everybody know whether or not it works.
GeneralWow! Thank you!memberJonny91230 Sep '07 - 16:00 
This is EXACTLY what I've been looking for. Thank you SO much! I love the way you wrote your article, as well as the code! You are truly a professional programmer! Wink | ;)
Generalthis is the work of a geniusmembermainpilot31 Aug '07 - 13:01 
subj
GeneralThanks!memberlcqishi27 Apr '07 - 17:08 
Big Grin | :-D
GeneralVery good !!nice!memberxuleidamao5 Apr '07 - 3:33 
Very good !!nice!
GeneralProbably ....memberV. Thieme11 Feb '07 - 6:05 
... an optical illusion but I think the rotating cube changes its edge length... May be it is a problem with my sight... Suspicious | :suss:
Great article. Thanks!!
 
*************************
Do, ut des.

General5!member¤ Muammar ¤5 Dec '06 - 22:03 
you're amazing, im sorry i cant give you 6Big Grin | :-D
GeneralNice, nice, nicememberVictorYoda30 Nov '06 - 9:21 
You've got my 5!
 
Do you happen to have a VS2003 version for this work?
 
Victor.
GeneralRe: Nice, nice, nicememberPete Everett30 Nov '06 - 13:14 
Thanks for your vote, Victor.
 
I don't actually have a VS2003 version of the code, primarily because I don't have VS2003 installed anywhere anymore, but I just breezed through the source code of the library, and it seems that it should be a pretty simple change to retrofit it for 1.1 support. I think that the only 2.0 feature I'm actually using is that I'm implementing the IEquatable<> interface in the Point3D and Vector3D structs. I'll bet that if you remove the reference to IEquatable in both of those source files, the code will compile just fine in .NET 1.1. Just create a new class library project in VS2003, then add the 5 .cs files from my project to it, and you should be up-and-running. I'm too lazy to look through the example code, but I'll bet it would be just as simple to tweak that for 1.1 support as well.
GeneralRe: Nice, nice, nicememberVictorYoda1 Dec '06 - 8:12 
Pete,
 
Dunn-it! Took two hours .. coffee breaks included; 'was indeed as you've predicted: took out IEquatable, Collections.Generic, a static class renamed etc.
Now I have a full working lib + example in VS2003!
Didn't do the NUnit test part -- you know ... too lazy.Big Grin | :-D
Thanks for the tips.
 
greetz,
Wink | ;-) Victor
QuestionDrawing POINTmemberedotekk29 Nov '06 - 3:23 
Is it possible to draw a single point in XYZ coordinate?
Please reply to me at the following email:
 
ederobbio@motoman.es
 
Thank you
Regards
 
Eduardo
AnswerRe: Drawing POINTmemberPete Everett29 Nov '06 - 3:39 
No. You can't really draw a point in this library. That's not too unusual, though, as you can't really draw a point in GDI+, either. You can kind of fake a point by drawing a stubby little line, but that doesn't work well, because a stubby line will be bigger if it's closer to you on the Z axis, and smaller if it's further away. The best bet, I think, would be to use the library to figure out the 2D coordinates of the 3D point you want to plot, then use a regular ol' GDI+ call to do the actual drawing. Here's how I see it working (very roughly, at least...this isn't what this library was designed to do). Keep in mind that this is off the top of my head, and completely untested, but it should approximate drawing a point in 3D:
 
 
using (Plotter3D p = new Plotter3D(someGraphicsObject, new Point3D(cameraX, cameraY, cameraZ)))
{
    // Figure out the flattened 2D coordinates of a 3D point
    PointF point = new Point3D(x, y, z).GetScreenPosition(p.CameraLocation);
 
    someGraphicsObject.DrawLine(Pens.Black, point.X, point.Y, point.X, point.Y + 1);
}
 

GeneralDrawing the x, y, z axesmemberPaul Selormey28 Nov '06 - 20:30 
What is the best way to handle drawing the axes and then plotting the points reference to the axes?
 
With love,
Paul.
 

 
Jesus Christ is LOVE! Please tell somebody.

AnswerRe: Drawing the x, y, z axesmemberPete Everett29 Nov '06 - 3:24 
Your question touches upon three things that this project isn't very good at doing.
 
First, drawing axes and plotting points relative to those axes smells a lot like absolute positioning (X, Y, Z) to me. This library is really designed to do relative positioning (Up, down, left, right). You can manage absolute positioning with the Plotter3D.MoveTo(Point3D) method, and that'll do what it sounds like you're looking for, but it's not really the focus of the library.
 
Second, it's not good at drawing infinite lines (like axis lines). If you draw a really long line along the z axis, it'll end up at a vanishing point, and it'll just look like a short stubby line. (You'll see what I'm talking about in the example).
 
And third, it's not good at drawing lines that extend past the camera position. So if you set up the Plotter3D at (for example) {0, 0, -100}, and you draw a line that extends to {0, 0, -200}, things get weird. It's important to keep the plotter positioned in front of the camera.
 
Anyway, here's some sample code to draw the X, Y, and Z axes.
 
    float xOrigin = 500;
    float yOrigin = 300;
    float zOrigin = 0;
 
    using (Plotter3D p = new Plotter3D(someGraphicsObject, 
             new Point3D(xOrigin - 100, yOrigin - 100, zOrigin - 1001)))
    {
        // draw the X axis
        p.PenColor = Color.Red;
        p.PenUp();
        p.MoveTo(new Point3D(xOrigin - 1000, yOrigin, zOrigin));
        p.PenDown();
        p.MoveTo(new Point3D(xOrigin + 1000, yOrigin, zOrigin));
 
        // draw the Y axis
        p.PenColor = Color.Blue;
        p.PenUp();
        p.MoveTo(new Point3D(xOrigin, yOrigin - 1000, zOrigin));
        p.PenDown();
        p.MoveTo(new Point3D(xOrigin, yOrigin + 1000, zOrigin));
 
        // draw the Z axis
        p.PenColor = Color.Green;
        p.PenUp();
        p.MoveTo(new Point3D(xOrigin, yOrigin, zOrigin - 1000));
        p.PenDown();
        p.MoveTo(new Point3D(xOrigin, yOrigin, zOrigin + 1000));
    }

 
Tom Hanks isn't a very good actor.
GeneralRe: Drawing the x, y, z axesmemberPaul Selormey29 Nov '06 - 23:08 
Thanks for the reply and the information. I was thinking if this library could be used as the basis to draw 3D charts, like Bar/Column charts, in which case the axes are not infinite.
I have even bought the book you recommended and will study the given code to see how far I could get with this project.
Again, thanks for the support.
Pete Everett wrote:
Tom Hanks isn't a very good actor.

He needs our prayer and love Rose | [Rose]
 
With love,
Paul.
 
Jesus Christ is LOVE! Please tell somebody.

GeneralExcellent articlememberWoody Green28 Sep '06 - 20:26 
This is an excellent article. Well written text and code. I am looking forward to your future articles!
 
Woody
Generalvery goodmemberbatlai24 Sep '06 - 20:37 
thanks .
GeneralSweeeet!memberziggy12314 Aug '06 - 17:23 
Great information! I'll surely be using this!
 
Thanks,
 
Ziggy
 
    www.ziggyware.com
      Advanced C# Tutorials
Game Development Resources

GeneralReally, really superb!memberJosh Smith6 Aug '06 - 5:49 
That is the first article about creating 3D graphics that really made sense to me. Thank you very much for writing it, and writing it so well. I can't wait to play around with your classes. Cool | :cool:
 
:josh:
My WPF Blog[^]

GeneralThanks, the 3D technologymemberLi Xiaojian(China)2 Aug '06 - 5:32 
I come from china, I have been add you blog http://blog.cynicalpirate.com to my favorite. This is my blog http://zklxj.cnblogs.com.Smile | :)
Generalthank youmemberlallous25 Jul '06 - 20:33 
Hello
 
Thank you for this nice article, keep the good work
 
Elias

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 9 Jun 2006
Article Copyright 2006 by Pete Everett
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid