Author Topic: .NET Graphics Components  (Read 7343 times)

0 Members and 1 Guest are viewing this topic.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7032
  • AKA Daniel
Re: .NET Graphics Components
« Reply #15 on: January 23, 2008, 09:54:00 AM »
Let me know what you think, Its a *Very* rough draft. I wanted to get opinions on moving the origin to the lower left before I went any further.  :mrgreen:

SomeCallMeDave

  • Guest
Re: .NET Graphics Components
« Reply #16 on: January 23, 2008, 10:15:22 AM »
IMO, moving the origin is a great idea.  Having it there makes 'plotting' points much more intuitive.

I'm hoping that I will have some time today or tomorrow to dig into it , if I can stop forex trading on that site that Mick posted :)

MickD

  • Gator
  • Posts: 3420
  • (x-in)->[process]->(y-out)
Re: .NET Graphics Components
« Reply #17 on: January 23, 2008, 04:13:58 PM »
IMO, moving the origin is a great idea.  Having it there makes 'plotting' points much more intuitive.

For a CAD type system that is the best choice as most understand the Cartesian coordinate system.

I'm not sure how GDI+ works in regards to panning and zooming, if this is required the origin will need to be re-calc'd in relation to the panel corner and the scene re-drawn to suit.
This is where I find lib's like Opengl are a bit more intuitive once you get going, they take care of the scene to screen transformations and others and let you draw in the 'scene' or model space.

Quote
I'm hoping that I will have some time today or tomorrow to dig into it , if I can stop forex trading on that site that Mick posted :)

hehe, addictive isn't it!
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

SomeCallMeDave

  • Guest
Re: .NET Graphics Components
« Reply #18 on: January 23, 2008, 06:26:44 PM »
hehe, addictive isn't it!

It is!  And it seems sooooo easy when I'm using their play-money  :-D



SomeCallMeDave

  • Guest
Re: .NET Graphics Components
« Reply #19 on: January 23, 2008, 06:29:44 PM »
So here is my attempt at extending Daniel's class.

It is still a very rough draft,  but it might have some potential.
Still needs lots of properties,  more constructors,.......

And it was a great learning exercise for me

Code: [Select]
        private void panel1_Paint(object sender, PaintEventArgs e)
        {
           
            DrawSpace drawSpace = new DrawSpace(panel1, e.Graphics);
            Pen pen = new Pen(Color.Black);//hmmm interesting

            Chart chart1 = new Chart(drawSpace, 100, 5);
            chart1.Draw();

        }


It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7032
  • AKA Daniel
Re: .NET Graphics Components
« Reply #20 on: January 23, 2008, 10:29:38 PM »
David, Very Nice
Do you mind if I add this in?

SomeCallMeDave

  • Guest
Re: .NET Graphics Components
« Reply #21 on: January 23, 2008, 10:37:58 PM »
Don't add it yet.

I had a few problems in that version.  I am cleaning those up and adding a few methods.

Code: [Select]

      private void panel1_Paint(object sender, PaintEventArgs e)
        {
           
            DrawSpace drawSpace = new DrawSpace(panel1, e.Graphics);
            Pen pen = new Pen(Color.Black)

            Chart chart1 = new Chart(drawSpace, 100, 100);
            chart1.HorizontalTicks = 10;
            chart1.VerticalTicks = 10;
            chart1.Draw();
            chart1.DrawBarVert(75, 10, 60, Color.Red);
            chart1.DrawBarHorz(55, 10, 50, Color.Blue);
            chart1.PlotPoint(10, 10, Color.Red, 3);
            chart1.PlotPoint(15, 15, Color.Red, 3);
            chart1.PlotPoint(20, 20, Color.Red, 3);

            PointF[] graph = new PointF[4];
            graph[0].X = 0; graph[0].Y = 0;
            graph[1].X = 10; graph[1].Y = 1;
            graph[2].X = 15; graph[2].Y = 45;
            graph[3].X = 66; graph[3].Y = 92;
            chart1.PlotLine(graph, Color.Purple);

        }


I will post a revised version later tonight or in the morning that I would be happy for you to add.

Also,  I have a design question.  For my new methods, I create Entity(s) in the method.  Should I call the draw method directly on the new Entitiy(s) from within that method.  Or would it be better to create an EntityList,  add the new Entity(s) to it, and then call the EntityList.draw  method in the Chart Draw override?

MickD

  • Gator
  • Posts: 3420
  • (x-in)->[process]->(y-out)
Re: .NET Graphics Components
« Reply #22 on: January 23, 2008, 10:56:54 PM »
...
Also,  I have a design question.  For my new methods, I create Entity(s) in the method.  Should I call the draw method directly on the new Entitiy(s) from within that method.  Or would it be better to create an EntityList,  add the new Entity(s) to it, and then call the EntityList.draw  method in the Chart Draw override?

Yes, creating a class that holds a list of entities would be the go, this way you are creating a scene graph or 'model' class to hold the entities, then from you panel's OnPaint() method (your panel would have a class member of your 'scene' class) you simply add a myScene.Draw() call to re-paint the scene with the objects.

You could also keep the scene class separate from the panel, this way you can draw the scene in any panel you like.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7032
  • AKA Daniel
Re: .NET Graphics Components
« Reply #23 on: January 23, 2008, 11:07:13 PM »
Also,  I have a design question.  For my new methods, I create Entity(s) in the method.  Should I call the draw method directly on the new Entitiy(s) from within that method.  Or would it be better to create an EntityList,  add the new Entity(s) to it, and then call the EntityList.draw  method in the Chart Draw override?

6 of 1, its really the same method in the end

I was thinking of making this an open source project, where people can add stuff when theyre not trading.  :laugh:
Im trying to learn how to use Marks subversion space, maybe this would be a good test project


MickD

  • Gator
  • Posts: 3420
  • (x-in)->[process]->(y-out)
Re: .NET Graphics Components
« Reply #24 on: January 23, 2008, 11:21:55 PM »
6 of 1, its really the same method in the end


not really, now the project is growing it's an ideal time to start using OOP to it's potential.

IOW, why not create say a class called ChartDrawableEnt as a base class which holds basic stuff like colours, line types etc then derive new types from it such as ChartBar, ChartLine etc.

Within wach of these derived classes you implement (override) a Draw() method which it inherits from the base, in here is where your drawing for that type of object mojo lives.

Now, once you have a few drawables it's really easy to add them to the 'scene' using polymorphism.

Scene scene = new Scene();
scene.AddEntity(myLine(p1, p2));
scene.AddEntity(myBar(p1, p2, width)
etc.
This can be done from the gui also.

Then in your panel paint method you just need to call scene.Draw(); to paint all of your objects.

Scene.Draw() would look something like this -

For each ChartDrawableEnt in entlist
    ent.Draw();

this is a much more dynamic solution I think.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7032
  • AKA Daniel
Re: .NET Graphics Components
« Reply #25 on: January 24, 2008, 12:12:09 AM »
Mick,

This is kind of what I have done.
I have a base class called Entity, that has a virtual method Draw(). There is also an EntityList class that also has a method called Draw(), that calls the Draw() method on each item in the collection. My thought was that new graphics should derive from the Entity class which can be added to the EntityList or drawn on its own

Here is where things get funky, since I have inverted the Y axis to move the origin to the lower left, some objects don’t behave well. For example text, I have to reset the matrix before the text is drawn or it will be inverted. I made a class called DrawSpace. It’s my idea that this class hold the matrix/space information, incase an Entity needs to temporarily alter the matrix or the origin.

Code: [Select]
private void panel1_Paint(object sender, PaintEventArgs e)
    {
      DrawSpace drawSpace = new DrawSpace(panel1, e.Graphics);
      Pen pen = new Pen(Color.PapayaWhip);
      EntityList eList = new EntityList();
      eList.Add(new Circle(drawSpace, new PointF(100, 100), 30, pen));
      eList.Add(new Line(drawSpace, new PointF(100, 100), new PointF(100, 200), pen));
      eList.Add(new Circle(drawSpace, drawSpace.LLPoint, 30, pen));
      eList.Add(new Arc(drawSpace, drawSpace.CenterPoint, 45, 0, 180, pen));
      eList.Draw();
    }

MickD

  • Gator
  • Posts: 3420
  • (x-in)->[process]->(y-out)
Re: .NET Graphics Components
« Reply #26 on: January 24, 2008, 12:48:00 AM »

In the code above I'd be adding the ent's in another method, maybe a draw graph button or OnInitPanel say. The only call I'd have in my paint method is eList.Draw(), this way your avoiding adding the ents every time the window paints!!

IRT to the DrawSpace, you should only need to have a method that transforms point data from panel coords to scene coord's, this is the last thing that needs doing before drawing, text may be a bit tricky as you say but you are only inverting the y axis in effect so you only need to change that I think.

You will probably need something like a graphics system ents that takes your scene coord's and xforms them just before painting, like the worldDraw() uses in arx.

In say your line class's draw method would then look something like this -

Draw()
{
   // get and set your pens etc here:
   gs.addLine(p1, p2);

}

and the gs.addLine method does the xform mojo. Does that make sense??
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

It's Alive!

  • BricsCAD
  • Needs a day job
  • Posts: 7032
  • AKA Daniel
Re: .NET Graphics Components
« Reply #27 on: January 24, 2008, 12:56:40 AM »
I agree that this would make sense from a performance point of view.
But how would I make the variables P1, and P2 dynamic in nature, without having to reconstruct the Entity?
Say if someone wanted to alter the value of P1 via a textbox.

MickD

  • Gator
  • Posts: 3420
  • (x-in)->[process]->(y-out)
Re: .NET Graphics Components
« Reply #28 on: January 24, 2008, 01:01:07 AM »
The pipeline goes something like this -

Add your objects to the scene
->
Model Transformation - translate the scene coord's to the view coord's (i.e. if you move the origin, all ents go too).
This involves clipping out things outside the panel, the panel should look after that though.
->
Viewing transformatiom - transforming all of the scene to fit into the viewport/panel, you would do this by scaling the scene coord's to the panel/viewport size.

I haven't looked at the gdi stuff at all and it may look after it all for you, it's good to know what's happening though.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.

MickD

  • Gator
  • Posts: 3420
  • (x-in)->[process]->(y-out)
Re: .NET Graphics Components
« Reply #29 on: January 24, 2008, 01:08:15 AM »
I agree that this would make sense from a performance point of view.
But how would I make the variables P1, and P2 dynamic in nature, without having to reconstruct the Entity?
Say if someone wanted to alter the value of P1 via a textbox.

Ok, this is where it gets 'deep', if you remember in arx how you add and get entities, you will need to do something like that, i.e. create a db of sorts so you can get your ent's by id (your ent lists is starting to look more like a dictionary ;) ).
How do you get the id from the ent with user interaction? good question, I haven't a clue with GDI+ but with most grfx lib's they have a selection buffer ability which is a bit hard to explain just now but if you want I can go through it with you.

This is the problem, the vast majority of examples show you the easiest ways to create and populate a graphics widget, what they don't go into is the complexity of making it dynamic and user interactive.
I love this stuff so if you want, just throw a question and I'll see if I can help, I'm a bit busy to jump in the app though.
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: To attain knowledge, add things
every day; to obtain wisdom, remove things every day.