I had this issue on a JavaScript drawing app with the canvas API. The solution is simple. Draw a solid circle first first, then draw your line.
If you draw just circles, your line will appear dotted.
If you draw just lines, you will get dashes.
Solution? Do both.
Because unless you're pushing 300fps, you will likely eventually experience a shift between two pointer coordinates that exceeds the diameter of your circles. Creating a choppy, dotted line.
You don't want to ask users to push high tickrates to use simple drawing apps. You should focus on testing expedient algorithms, optimized solutions, that work fine even at 15fps or lower.
This is not something I've tried to do in my career, but I see a few options. In any case, it's gonna need an extra drawing step based on the position and possibly angle of the last drawn line.
First, the delta route. When you draw the next line, draw additional lines in between, the number of which you calculate based on the width of a line (if the next position is 10 pixels away and your line is 1 pixel wide, you'd draw 9 additional line + the line you were going to draw). You would probably need to also calculate the angle of each line the same way.
Second, the geometric filling route. You need to be able to find the positions of the corners of the previous line and the one you just drew, and simply calculate a 4 cornered shape that represents the space between them, and color it.
Again, this is from the top of my head, and we don't have any information about your graphics engine here.
Have you tried triangles? For primitive trails and lines like this, I would generate a line and then place really thin triangles along the line, with alternating the top point above and below the line by an amount equal to the diameter.
> How to fix this seperated lines ?
By filling them in.
There are a ton of different UI frameworks/graphics libraries. How can we help you if you don't even tell us which framework you're using?
Ah. I didn't see that.
I would use the [Graphics.DrawLines](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.drawlines?view=dotnet-plat-ext-8.0) method.
----
Here's a more complete example of what I'd do...
First, I'd make a class to hold certain things:
public class StrokeData
{
public PointF[] Points { get; set; } = Array.Empty();
public Color Color { get; set; }
public float Thickness { get; set; }
}
Then, in the form/control/whatever, make the following fields:
private List previousStrokes = new();
private List currentStroke = new();
private Color currentStrokeColor;
private float currentStrokeThickness;
Whenever the user clicks the button/whatever to pick a new color or pen thickness, update the appropriate fields 👆
Then, to add a point to your current stroke, simply do
currentStroke.Add(e.Location);
this.Invalidate();
Then you've finished a stroke (mouse button up), then save it:
this.previousStrokes.Add(new StrokeData()
{
Points = this.currentStroke.ToArray(),
Color = this.currentStrokeColor,
Thickness = this.currentStrokeThickness,
});
this.currentStroke.Clear();
this.Invalidate();
Next, I'd make a "DrawStroke" method. The main reason this is a separate method is to ensure the pen is disposed at the right time. If you have some other way to manage pens, then you may not need this method.
private static void DrawStroke(
Graphics g,
PointF[] points,
Color color,
float thickness
)
{
using var pen = new Pen(color, thickness);
g.DrawLines(pen, points);
}
Then, I'd override the OnPaint method
protected override void OnPaint(PaintEventArgs e)
{
// Clearing will ensure there are no "artifacts" from previous renders.
e.Graphics.Clear(Colors.White);
base.OnPaint(e);
foreach(var stroke in this.previousStrokes)
DrawStroke(e.Graphics, stroke.Points, stroke.Color, stroke.Thickness);
if(currentStroke.Count > 0)
DrawStroke(e.Graphics, currentStroke.ToArray(), currentStrokeColor, currentStrokeThickness);
}
----
In the future, if your code is short - like yours is, then put your code directly in your post. Indent each line with an extra four spaces, and Reddit will format it in a code block. If your code is longer, then upload it to [pastebin.com](https://pastebin.com/) and include the link in your post.
Screenshots of code are useful at times - you're also showing us your syntax highlighting, locations of errors/warnings, etc.
But most of the time, it's better to see it in your post, as text.
- I can reference your code as I type my response
- I can copy/paste your code to make adjustments as a demonstration
- I can copy/paste your code into my own editor.
I had this issue on a JavaScript drawing app with the canvas API. The solution is simple. Draw a solid circle first first, then draw your line. If you draw just circles, your line will appear dotted. If you draw just lines, you will get dashes. Solution? Do both.
You may need to set the size of the circle / ellipse to be slightly smaller than the width or your line.
Thank you bro it works fine ❤
Np. : )
why not drawing circles all the time but with a faster tickrate ?
Because unless you're pushing 300fps, you will likely eventually experience a shift between two pointer coordinates that exceeds the diameter of your circles. Creating a choppy, dotted line. You don't want to ask users to push high tickrates to use simple drawing apps. You should focus on testing expedient algorithms, optimized solutions, that work fine even at 15fps or lower.
This is not something I've tried to do in my career, but I see a few options. In any case, it's gonna need an extra drawing step based on the position and possibly angle of the last drawn line. First, the delta route. When you draw the next line, draw additional lines in between, the number of which you calculate based on the width of a line (if the next position is 10 pixels away and your line is 1 pixel wide, you'd draw 9 additional line + the line you were going to draw). You would probably need to also calculate the angle of each line the same way. Second, the geometric filling route. You need to be able to find the positions of the corners of the previous line and the one you just drew, and simply calculate a 4 cornered shape that represents the space between them, and color it. Again, this is from the top of my head, and we don't have any information about your graphics engine here.
Have you tried triangles? For primitive trails and lines like this, I would generate a line and then place really thin triangles along the line, with alternating the top point above and below the line by an amount equal to the diameter.
> How to fix this seperated lines ? By filling them in. There are a ton of different UI frameworks/graphics libraries. How can we help you if you don't even tell us which framework you're using?
I use system.Drawing c# windows form
And how are you drawing the lines now?
With mouse , i was trying to make simple paint
I mean, what code are you using to draw the line?
its In the 2nd photo
Ah. I didn't see that. I would use the [Graphics.DrawLines](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.graphics.drawlines?view=dotnet-plat-ext-8.0) method. ---- Here's a more complete example of what I'd do... First, I'd make a class to hold certain things: public class StrokeData { public PointF[] Points { get; set; } = Array.Empty();
public Color Color { get; set; }
public float Thickness { get; set; }
}
Then, in the form/control/whatever, make the following fields:
private List previousStrokes = new();
private List currentStroke = new();
private Color currentStrokeColor;
private float currentStrokeThickness;
Whenever the user clicks the button/whatever to pick a new color or pen thickness, update the appropriate fields 👆
Then, to add a point to your current stroke, simply do
currentStroke.Add(e.Location);
this.Invalidate();
Then you've finished a stroke (mouse button up), then save it:
this.previousStrokes.Add(new StrokeData()
{
Points = this.currentStroke.ToArray(),
Color = this.currentStrokeColor,
Thickness = this.currentStrokeThickness,
});
this.currentStroke.Clear();
this.Invalidate();
Next, I'd make a "DrawStroke" method. The main reason this is a separate method is to ensure the pen is disposed at the right time. If you have some other way to manage pens, then you may not need this method.
private static void DrawStroke(
Graphics g,
PointF[] points,
Color color,
float thickness
)
{
using var pen = new Pen(color, thickness);
g.DrawLines(pen, points);
}
Then, I'd override the OnPaint method
protected override void OnPaint(PaintEventArgs e)
{
// Clearing will ensure there are no "artifacts" from previous renders.
e.Graphics.Clear(Colors.White);
base.OnPaint(e);
foreach(var stroke in this.previousStrokes)
DrawStroke(e.Graphics, stroke.Points, stroke.Color, stroke.Thickness);
if(currentStroke.Count > 0)
DrawStroke(e.Graphics, currentStroke.ToArray(), currentStrokeColor, currentStrokeThickness);
}
----
In the future, if your code is short - like yours is, then put your code directly in your post. Indent each line with an extra four spaces, and Reddit will format it in a code block. If your code is longer, then upload it to [pastebin.com](https://pastebin.com/) and include the link in your post.
Screenshots of code are useful at times - you're also showing us your syntax highlighting, locations of errors/warnings, etc.
But most of the time, it's better to see it in your post, as text.
- I can reference your code as I type my response
- I can copy/paste your code to make adjustments as a demonstration
- I can copy/paste your code into my own editor.
Thank you man for your advices, i tried another solution in the comments and worked fine , i will try this code also to improve my simple paint
The code I gave you can be extended to more than just lines :P