Page Index Toggle Pages: 1 [2]  Send TopicPrint
Hot Topic (More than 10 Replies) How do you turn a DiagramView into a Bitmap? (Read 1472 times)
koichi_satoh
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 25
Joined: Nov 30th, 2023
Re: How do you turn a DiagramView into a Bitmap?
Reply #15 - Jun 26th, 2024 at 5:35am
Print Post  
Sorry. I guess I didn't explain it well.

Currently, I have the following component configuration, as shown in the sample.zip I attached previously.

DiagramView
 ∟CompositeNode
  ∟UserControl(OnFocus)
  ∟Bitmap(FocusOut)

Bitmap is Component.Added to CompositeNode, and UserControl is set to EditControl of CompositeNode.

When CompositeNode is focused out, the contents of UserControl are converted to Bitmap, but I can't fix the issue where the coordinates of the generated Bitmap are misaligned, and I'm having trouble with that.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3262
Joined: Oct 19th, 2005
Re: How do you turn a DiagramView into a Bitmap?
Reply #16 - Jun 27th, 2024 at 12:16pm
Print Post  
If I understand the test project correctly, GridNode only draws a bitmap. When the mouse pointer enters a node, CreateCustomEditControl adds a grid control on top of it as an editor, and mouse-leave regenerates GridNode.Image.

So if you need to create pixel-perfect alignment of the pop-over grid with GridNode.Image, you must keep in mind that WinForms can show that child grid only at integer pixel coordinates. Following seems to work well on my system:

Code
Select All
//gridNode.Bounds = new RectangleF(10, 10, 200, 150);
gridNode.Bounds = diagramView.ClientToDoc(
	diagramView.DocToClient(new RectangleF(10, 10, 200, 150)));
 



here nested DocToClient returning pixel values, and outer ClientToDoc returning diagram coords for them. Then also shifting the grid by one pixel in CreateCustomEditControl:

Code
Select All
if (e.Node == this)
{
    e.EditControl = GridView;
    var pixelRect = _view.DocToClient(Bounds);
    pixelRect.X += 1;
    pixelRect.Y += 1;
    e.EditControl.Bounds = pixelRect;
} 



Not sure why that's needed: either GridView.DrawToBitmap excludes border thickness, or the ClientToDoc(DocToClient) combo always rounds down, but has to round up if fraction part of coordinate is larger than 0.5. Try playing with different Bounds values to see if it's the latter case. Then you could determine whether to shift by 1 by checking the fraction part of DocToClientF result.

If you'll be aligning the node to pixels as above and letting users draw interactively, you can apply those operations from NodeCreated and NodeModified event handlers.

Some other options you might try:

- change diagram's MeasureUnit to Pixel;
- override GridView drawing code and translate by that factional part of DocToClientF before calling base;

Regards,
Slavcho
Mindfusion
« Last Edit: Jun 27th, 2024 at 3:14pm by Slavcho »  
Back to top
 
IP Logged
 
koichi_satoh
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 25
Joined: Nov 30th, 2023
Re: How do you turn a DiagramView into a Bitmap?
Reply #17 - Jun 28th, 2024 at 12:10am
Print Post  
We've also incorporated logic to shift by 1 pixel here.
However, the 1 pixel shift may or may not occur depending on the coordinates and size of the CompositeNode, so it seems that a uniform shift of 1 pixel won't work.
We'll make this an internal restriction for the time being.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3262
Joined: Oct 19th, 2005
Re: How do you turn a DiagramView into a Bitmap?
Reply #18 - Jun 28th, 2024 at 6:25am
Print Post  
Code
Select All
e.EditControl = GridView;

var pixelRectF = _view.DocToClientF(Bounds);
var xFraction = pixelRectF.X - Math.Truncate(pixelRectF.X);
var yFraction = pixelRectF.Y - Math.Truncate(pixelRectF.Y);

var pixelRect = _view.DocToClient(Bounds);
if (xFraction >= 0.5)
    pixelRect.X += 1;
if (yFraction >= 0.5)
    pixelRect.Y += 1;

e.EditControl.Bounds = pixelRect; 



should work correctly, but I've tried it with only a few different values of gridNode.Bounds. That would still require you to align gridNode.Bounds to pixels via ClientToDoc(DocToClient) to avoid sub-pixel difference, which could show e.g. via anti-aliasing.

Regards,
Slavcho
Mindfusion
  
Back to top
 
IP Logged
 
koichi_satoh
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 25
Joined: Nov 30th, 2023
Re: How do you turn a DiagramView into a Bitmap?
Reply #19 - Jul 1st, 2024 at 7:48am
Print Post  
Thank you for considering the correction logic.
I tried it out, and it certainly does not shift easily, but there are still cases where it shifts depending on the coordinates and size.

I will consider a solution to correct the coordinates or size so that no decimal points are generated in DocToClientF when moving or resizing.
  
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3262
Joined: Oct 19th, 2005
Re: How do you turn a DiagramView into a Bitmap?
Reply #20 - Jul 1st, 2024 at 11:45am
Print Post  
Do you call ClientToDoc(DocToClient(...)) to align to pixels from these event handlers?

Quote:
If you'll be aligning the node to pixels as above and letting users draw interactively, you can apply those operations from NodeCreated and NodeModified event handlers.
  
Back to top
 
IP Logged
 
koichi_satoh
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 25
Joined: Nov 30th, 2023
Re: How do you turn a DiagramView into a Bitmap?
Reply #21 - Jul 2nd, 2024 at 10:25am
Print Post  
I made corrections to the areas framed in red in the two attached files, but when I change the top left coordinate, the image shifts when I focus out.
Are the corrections correct?
  

MyEditSource.bmp ( 2153 KB | 26 Downloads )
MyEditSource.bmp
Back to top
 
IP Logged
 
Slavcho
YaBB Moderator
*****
Offline


tech.support

Posts: 3262
Joined: Oct 19th, 2005
Re: How do you turn a DiagramView into a Bitmap?
Reply #22 - Jul 5th, 2024 at 6:47am
Print Post  
Quote:
but when I change the top left coordinate


If you mean resizing interactively, the node could lose its alignment to screen pixel once you drag the top-left corner to a new position. Try resetting e.Node.Bounds to ClientToDoc(DocToClient(e.Node.Bounds)) from NodeModified event handler to keep it aligned, as suggested in post above.

I.e. what happens in the Form_Load event from screenshot, should happen in NodeModified too, because the diagram could convert mouse location to floating point coordinates. If you let your users draw new nodes interactively, do that from NodeCreated event handler as well.

Finally, if pixel alignment is that important for your application, maybe switch Diagram.MeasureUnit to Pixel. However, the diagram could still convert mouse input to floating point coordinates if you let users change zoom level: e.g. a screen pixel with x =1 could convert to 1.5 diagram coordinate at 66% zoom level (== 1 / 1.5).

Regards,
Slavcho
Mindfusion
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1 [2] 
Send TopicPrint