0

Let me describe an issue that is taking me more than one day to solve so far. I am inputting a series of lines from a text file and I want to draw a picture with them. The thing is that two of these lines are too close (1 pixel distance) which is a problem if a Pen of Thickness is=1 is used. See the problematic region below:

enter image description here

For information, the bounding rectangle of the lines in the text file representing the whole shape is as follows:

Rectangle(xmin, ymin, (xmax - xmin), (ymax - ymin)) =  761, 236, 298, 344

And I am trying to draw them to a Bitmap(20000, 15000) but the size of the Bitmap could be changed if necessary.

My questions are:

  • Is there a workaround to make the pen thickness smaller than 1 to avoid such overlap?
  • Would it be possible to modify the input coordinates a little bit (some sort of “dilatation”) so this issue does not happen?

Otherwise, can someone think about another solution to solve this issue?

Thank you very much,

My code:

using System;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;


namespace DrawingLinesTest
{
class Program
{

    static void Main(string[] args)
    {
        //Define the input txt file
        System.IO.StreamReader file = new System.IO.StreamReader("input.txt");
        //Define the bmp
        Bitmap bmp = new Bitmap(20000, 15000); 
        Graphics g = Graphics.FromImage(bmp);
        Pen blackPen = new Pen(Color.FromArgb(255, 0, 0, 0), 1);


        // Read the file
        int counter = 0;
        string line;
        var listX1 = new List<int>();
        var listY1 = new List<int>();
        var listX2 = new List<int>();
        var listY2 = new List<int>();
        var allPoints = new List<Point>();


        while ((line = file.ReadLine()) != null)
        {
            string[] points = line.Split(',');
            int x1 = int.Parse(points[0]), y1 = int.Parse(points[1]), x2 = int.Parse(points[2]), y2 = int.Parse(points[3]);
            int[] pInt = new int[4] { x1, y1, x2, y2 };
            listX1.Add(x1); listY1.Add(y1); listX2.Add(x2); listY2.Add(y2);

            Point a = new Point(int.Parse(points[0]), int.Parse(points[1]));
            Point b = new Point(int.Parse(points[2]), int.Parse(points[3]));               

            allPoints.Add(a); allPoints.Add(b);
            g.DrawLine(blackPen, a, b);                
            counter++;
        }
        file.Close();
        g.Dispose();
        //-----------------------------------------------------------------------------------------------------------------------------------------------
        // Find the list's bounding box.
        IEnumerable<Point> po = allPoints;
        Rectangle r = BoundingBox(po);
        Console.WriteLine(String.Format("Bounding Box {0},{1},{2},{3}", r.X, r.Y, r.Width, r.Height));

        Bitmap nb = new Bitmap(r.Width, r.Height);
        Graphics gr = Graphics.FromImage(nb);
        gr.DrawImage(bmp, -r.X, -r.Y);

        //Save input file as an image (output)
        nb.Save("outputPicture.png");
        //-----------------------------------------------------------------------------------------------------------------------------------------------

    }


    public static Rectangle BoundingBox(IEnumerable<Point> points)
    {
        var x_query = from Point p in points select p.X;
        int xmin = x_query.Min();
        int xmax = x_query.Max();

        var y_query = from Point p in points select p.Y;
        int ymin = y_query.Min();
        int ymax = y_query.Max();

        return new Rectangle(xmin, ymin, (xmax - xmin), (ymax - ymin));        }

}//end Program
}//end Namespace
user3641829
  • 261
  • 2
  • 11
  • 1
    Double the size of the image and the coordinates, that should result in finer detail. – DavidG Jul 17 '15 at 11:50
  • Well, you __can__ set the Pen.width to some fraction, like 0.5f but the result will be aliasing pixels. So other than make the image still larger there is nothing much you can do short of changing the lines themselves. Which is not really easy either. Or you could play with the Pen.Alignment. This might help if your lines are drawn in closed groups using DrawLines. (Note the plural!) - What is the problem with the touching pixels? – TaW Jul 17 '15 at 12:04
  • You should not `int.Parse()` your lines two times. – DrKoch Jul 17 '15 at 12:43

1 Answers1

0

Some Background:

In graphics you have to deal with several coordinate syetems:

  1. World coordinates, for example in meters. In your case these are the coordinates in the text file
  2. Canvas coordinates / Bitmap coordinates, usually in Pixels, these are the pixels in the generated image.

Then you have some coordinate-transformation from world coordinates to canvas coordinates. You omitted this step, which generates your problems.

If you create a coordinate conversion for example 1 unit in world -> 10 Pixels all your problems go away.

EDIT

In your case a multiplication by 10 will do:

        Point a = new Point(int.Parse(points[0]*10), int.Parse(points[1]*10));
        Point b = new Point(int.Parse(points[2]*10), int.Parse(points[3]*10));    
DrKoch
  • 9,556
  • 2
  • 34
  • 43
  • You __did__ read the OP is using a `Bitmap(20000, 15000)` already? – TaW Jul 17 '15 at 12:34
  • Yes, but the coordinate conversion (multiply input coordinates by something like 10) **is missing** – DrKoch Jul 17 '15 at 12:38
  • @TaW Many thanks, I have tried it with the bounding rectangle part in the code commented out and it works. However if I want to fit the image to the screen (bounding rectangle is not commented out) then I get an "out of memory exception" issue. Any ideas why? – user3641829 Jul 17 '15 at 14:02
  • You can't create arbitrarily large Bitmaps. [See here](http://stackoverflow.com/questions/6333681/c-sharp-parameter-is-not-valid-creating-new-bitmap) – TaW Jul 17 '15 at 14:24