MFC Line drawing and selection problem..... 
Author Message
 MFC Line drawing and selection problem.....

Hi,

I'm trying to make a program where you can draw lines and select them. So
far I can do this, but I have a problem. To select a line, you have to make
a selection rectangle around the line. This would be okay, except for
sometimes the larger lines' rectangles cover the smaller lines' selection
rectangles, and they become unselectable.

now, I know there is a way to make the line only selectable by clicking near
to it (like 10 or so points away), without having a massive selection
rectangle. Is there anyone who knows the code snippet, or who has it
anywhere, that could bung it up on here to help me ? I'd be sooo greatful...

My current code for selection looks like this :-

BOOL CLine::PtInLine(POINT point)

{
    int dx = abs(m_ptFrom.x - m_ptTo.x);
    int dy = abs(m_ptFrom.y - m_ptTo.y);

    if (abs(m_ptFrom.x - point.x) < (dx-30) && abs(m_ptTo.x - point.x) <
(dx-30))
    {
        if (abs(m_ptFrom.y - point.y) < (dy-30) && abs(m_ptTo.y - point.y) <
(dy-30))
        {
            return TRUE;
        }
        else
        {
        return FALSE;
        }
    }
    else
    {
    return FALSE;
    }

Quote:
} // end BOOL CLine::PtInLine(POINT point)

Any help greatfully received.
Regards
Dan


Thu, 24 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....
Hi Opal,
I've done this with CRgn.
In my program there are several objects with lines,curves etc.
for select them with the mouse I use:
pDC->BeginPath
pDC->..DrawingFcts
pDC->EndPath
CreateRgnFromPath
rgn.PtInRgn
By Schiko



Quote:
> Hi,

> I'm trying to make a program where you can draw lines and select them. So
> far I can do this, but I have a problem. To select a line, you have to
make
> a selection rectangle around the line. This would be okay, except for
> sometimes the larger lines' rectangles cover the smaller lines' selection
> rectangles, and they become unselectable.

> now, I know there is a way to make the line only selectable by clicking
near
> to it (like 10 or so points away), without having a massive selection
> rectangle. Is there anyone who knows the code snippet, or who has it
> anywhere, that could bung it up on here to help me ? I'd be sooo
greatful...

> My current code for selection looks like this :-

> BOOL CLine::PtInLine(POINT point)

> {
>     int dx = abs(m_ptFrom.x - m_ptTo.x);
>     int dy = abs(m_ptFrom.y - m_ptTo.y);

>     if (abs(m_ptFrom.x - point.x) < (dx-30) && abs(m_ptTo.x - point.x) <
> (dx-30))
>     {
>         if (abs(m_ptFrom.y - point.y) < (dy-30) && abs(m_ptTo.y - point.y)
<
> (dy-30))
>         {
>             return TRUE;
>         }
>         else
>         {
>         return FALSE;
>         }
>     }
>     else
>     {
>     return FALSE;
>     }
> } // end BOOL CLine::PtInLine(POINT point)

> Any help greatfully received.
> Regards
> Dan



Thu, 24 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....
I'm also looking for it... the way would be to remember my geometry course,
and calculate the distance between a point and a line... if you find it, it
would be great to mail me...(and if I find, I'll mail you...)

Thanx.

You wanna see what a bug is?: visit http://graff.ctw.net and download Graff
beta 1.02 (in french, if you want an english version mail me)



Thu, 24 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....
I was suggesting a divide-and-conquer algorithm in an earlier post. If
you don't have hundreds or thousands of objects, the solution below is
excellent.
                                joe

On Sun, 7 May 2000 15:52:04 +0200, "Schiko"

Quote:

>Hi Opal,
>I've done this with CRgn.
>In my program there are several objects with lines,curves etc.
>for select them with the mouse I use:
>pDC->BeginPath
>pDC->..DrawingFcts
>pDC->EndPath
>CreateRgnFromPath
>rgn.PtInRgn
>By Schiko



>> Hi,

>> I'm trying to make a program where you can draw lines and select them. So
>> far I can do this, but I have a problem. To select a line, you have to
>make
>> a selection rectangle around the line. This would be okay, except for
>> sometimes the larger lines' rectangles cover the smaller lines' selection
>> rectangles, and they become unselectable.

>> now, I know there is a way to make the line only selectable by clicking
>near
>> to it (like 10 or so points away), without having a massive selection
>> rectangle. Is there anyone who knows the code snippet, or who has it
>> anywhere, that could bung it up on here to help me ? I'd be sooo
>greatful...

>> My current code for selection looks like this :-

>> BOOL CLine::PtInLine(POINT point)

>> {
>>     int dx = abs(m_ptFrom.x - m_ptTo.x);
>>     int dy = abs(m_ptFrom.y - m_ptTo.y);

>>     if (abs(m_ptFrom.x - point.x) < (dx-30) && abs(m_ptTo.x - point.x) <
>> (dx-30))
>>     {
>>         if (abs(m_ptFrom.y - point.y) < (dy-30) && abs(m_ptTo.y - point.y)
><
>> (dy-30))
>>         {
>>             return TRUE;
>>         }
>>         else
>>         {
>>         return FALSE;
>>         }
>>     }
>>     else
>>     {
>>     return FALSE;
>>     }
>> } // end BOOL CLine::PtInLine(POINT point)

>> Any help greatfully received.
>> Regards
>> Dan

Joseph M. Newcomer [MVP]

Web: http://www3.pgh.net/~newcomer
MVP Tips: http://www3.pgh.net/~newcomer/mvp_tips.htm


Thu, 24 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....
yes but no...

Rgn are good if you want to know if the user clicked exactly on the line,
but not around the line... (and it become stranger with a set of line
segment...). So if you have a better solution it would be good ;-)

Tenebrax



Thu, 24 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....

Quote:
> I was suggesting a divide-and-conquer algorithm in an earlier post. If
> you don't have hundreds or thousands of objects, the solution below is
> excellent.

It would be very kind if you could gimme more info about this
divide-and-conquer algo... (url or post)

Thanx

Tenebrax

note: I'm on this newsgroup for not a long time, so I don't have all the
post (and don't have enough money to download all the post....).



Thu, 24 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....


Fri, 19 Jun 1992 00:00:00 GMT  
 MFC Line drawing and selection problem.....
Hi ppl !!!

ok, i've got a Half working answer.... but this only works for straight
lines !!!

I'll give you the description, then i'll post the code...

Going back to my old A-Level maths books (yes, i'm English ;-D ) I found
some stuff on coordinate geometry. Now basically, for straight lines...

if you work out the Gradient of the line, this is derived from :-

increase in Y
------------------
increase in X

then, once you have drawn a line, you "Should" know it's start and end
points.
Using the equation of a line, which is derived from :-

Y = GX-C

put in any point on the line, the start point will do, and the gradient.
Re-Arrange to get C.

C = GX - Y

Ok, once you have the answer to C, then you want to do a hit test.

so take the point.x and point.y from the mouse and test them.

using the first equation Y=GX-C

put in the X value from the mouse.
Put in the gradient of the line you are checking.
Put in the value of C you got earlier.

if point.y = y from the equation, then HIT = TRUE !!!! ;-) yay.

so far, this only works for hitting right on the line though, and we also
want be able to have a small buffer area around the line so that you don't
have to click right to the very pixel on the line. Not only this, the
equations are a bit erroneuos as POINTS are always INTs. so re-arranging the
equation to give us a buffer and only use integers gives us this......

substituting the gradient out.

c(xInc) = point.y(xInc) -yInc(point.x).

This WORKS !!!!! I'll show the code in a sec and all will become clearer.
The only problem with this is that there is no bounds checking. If you
follow a line's gradient past the end of a line, it is still selectable (the
mouseclick POINT still falls on the line according to the line's equation).
I've tried bound testing this, but to no avail, so someone please help us
out here ! We'll have a killer method if we can crack it !!!

Regards
Dan

Code follows.
-------------------

BOOL CLine::PtInLine(POINT point)
{

    // we need to find the gradient of the line so
    // as stated in my old A-Level maths book...
    // increase in y/increase in x = gradient.

    int xInc = (m_ptFrom.x - m_ptTo.x);
    int yInc = (m_ptFrom.y - m_ptTo.y);

    // Now, we need the equation of the line.
    // This is given by y=gx+c...
    // we need to re-arrange this to get c
    // c = y - gx

    // take into consideration that INT is more
    // accurate than LONG or DOUBLE, lets re-arrange
    // the equation so we don't have to do any division
    // subs g(gradient) for yInc/xInc gives us.....

    // y(xInc) = x(yInc) - c(xInc)

    // these are calculated below

    int cxInc = ( (m_ptFrom.y*xInc) - (m_ptFrom.x*yInc) );
    int yxInc = (point.y*xInc);
    int xyInc = (point.x*yInc);

    // these are to give us a small buffer area around the
    // line so you don't have to click right on the line

    int cxIncLo = cxInc - 2000;
    int cxIncHi = cxInc + 2000;

    // I don't know why 2000, but it seems to work.

    // then the equation

    if (yxInc > (xyInc + cxIncLo) &&
        yxInc < (xyInc + cxIncHi) )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }

Quote:
} // end

>yes but no...

>Rgn are good if you want to know if the user clicked exactly on the line,
>but not around the line... (and it become stranger with a set of line
>segment...). So if you have a better solution it would be good ;-)

>Tenebrax



Fri, 25 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....


Fri, 19 Jun 1992 00:00:00 GMT  
 MFC Line drawing and selection problem.....

Quote:
> I'm trying to make a program where you can draw lines and select them.

Here's some code that works for me.  I didn't write it myself, though!
In the code below, a line can consist of multiple line fragments, which
by themselves are straight lines between coordinates.  In other words, a
line consists of a list (m_list) of coordinates.

The function returns the smallest distance between a point (parameter
CPoint point; in my app usually the mous cursor) and the nearest-by line
fragment.  On return, the parameter NearestLine contains the index (in
m_list) to the line fragment that's closest to CPoint point; the
parameter NearestPoint holds the point ON that line fragment that is
closest (again) to CPoint point.

I e-mailed the code below to someone else before, and he ported it to
his app without problems.  So I hope this helps for you too!

Cheers,

Jaco.

======================================================================
#include <math.h>
#define sqr(x) ((x)*(x))

float CLine::IsHit(CPoint point, CPoint &NearestPoint, int &NearestLine)
{
        double SmallestDistance = 2000.0f, Distance, Factor, Length;
        int PointX, PointY, LineX, LineY;

        for(int Coor = 0; Coor < m_list.GetSize() - 1; Coor++)
        {
                LineX = m_list[Coor + 1].x - m_list[Coor].x;
                LineY = m_list[Coor + 1].y - m_list[Coor].y;

                PointX = point.x - m_list[Coor].x;
                PointY = point.y - m_list[Coor].y;

                Length = sqrt(sqr(LineX) + sqr(LineY));
                Factor = ((LineX / Length) * PointX + (LineY / Length) * PointY) /
Length;

                if(Factor > 0.0f && Factor < 1.0)
                {
                        PointX = (int) (m_list[Coor].x + Factor * LineX);
                        PointY = (int) (m_list[Coor].y + Factor * LineY);

                        Distance = sqr(point.x - PointX) + sqr(point.y - PointY);

                        if(Distance < SmallestDistance)
                        {
                                NearestPoint.x = PointX;
                                NearestPoint.y = PointY;
                                SmallestDistance = Distance;
                                NearestLine = Coor;
                        }
                }
                else
                {
                        Distance = sqr(point.x - m_list[Coor].x) + sqr(point.y -
m_list[Coor].y);

                        if(Distance < SmallestDistance)
                        {
                                NearestPoint = m_list[Coor];
                                SmallestDistance = Distance;
                                NearestLine = Coor;
                        }

                        Distance = sqr(point.x - m_list[Coor + 1].x) + sqr(point.y -
m_list[Coor + 1].y);

                        if(Distance < SmallestDistance)
                        {
                                NearestPoint = m_list[Coor + 1];
                                SmallestDistance = Distance;
                                NearestLine = Coor + 1;
                        }
                }
        }

        return (float) sqrt(SmallestDistance);

Quote:
}

===============================================================


Fri, 25 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....


Fri, 19 Jun 1992 00:00:00 GMT  
 MFC Line drawing and selection problem.....
You need to add a simple test: compute a normalized bounding box of
the line, that is, create a CRect r(x0, y0, x1, y1) and call
r.NormalizeRect() which gets it into the right order in case the line
was drawn right-to-left or bottom-to-top. Then test if mousex >
r.right or mousex < r.left or mousex > r.bottom or mousex < r.top and
if any of those are true, you are outside the line.

Note also that in the region-hit-point test method, there is nothing
that says you have to draw the path with the same-size pen as you drew
the line or curve; if, instead, you draw it with a wider pen (your
buffer zone size), then the region hit test should do the job.
                                joe

On Mon, 08 May 2000 12:18:29 GMT, "Opal"

Quote:

>Hi ppl !!!

>ok, i've got a Half working answer.... but this only works for straight
>lines !!!

>I'll give you the description, then i'll post the code...

>Going back to my old A-Level maths books (yes, i'm English ;-D ) I found
>some stuff on coordinate geometry. Now basically, for straight lines...

>if you work out the Gradient of the line, this is derived from :-

>increase in Y
>------------------
>increase in X

>then, once you have drawn a line, you "Should" know it's start and end
>points.
>Using the equation of a line, which is derived from :-

>Y = GX-C

>put in any point on the line, the start point will do, and the gradient.
>Re-Arrange to get C.

>C = GX - Y

>Ok, once you have the answer to C, then you want to do a hit test.

>so take the point.x and point.y from the mouse and test them.

>using the first equation Y=GX-C

>put in the X value from the mouse.
>Put in the gradient of the line you are checking.
>Put in the value of C you got earlier.

>if point.y = y from the equation, then HIT = TRUE !!!! ;-) yay.

>so far, this only works for hitting right on the line though, and we also
>want be able to have a small buffer area around the line so that you don't
>have to click right to the very pixel on the line. Not only this, the
>equations are a bit erroneuos as POINTS are always INTs. so re-arranging the
>equation to give us a buffer and only use integers gives us this......

>substituting the gradient out.

>c(xInc) = point.y(xInc) -yInc(point.x).

>This WORKS !!!!! I'll show the code in a sec and all will become clearer.
>The only problem with this is that there is no bounds checking. If you
>follow a line's gradient past the end of a line, it is still selectable (the
>mouseclick POINT still falls on the line according to the line's equation).
>I've tried bound testing this, but to no avail, so someone please help us
>out here ! We'll have a killer method if we can crack it !!!

>Regards
>Dan

>Code follows.
>-------------------

>BOOL CLine::PtInLine(POINT point)
>{

>    // we need to find the gradient of the line so
>    // as stated in my old A-Level maths book...
>    // increase in y/increase in x = gradient.

>    int xInc = (m_ptFrom.x - m_ptTo.x);
>    int yInc = (m_ptFrom.y - m_ptTo.y);

>    // Now, we need the equation of the line.
>    // This is given by y=gx+c...
>    // we need to re-arrange this to get c
>    // c = y - gx

>    // take into consideration that INT is more
>    // accurate than LONG or DOUBLE, lets re-arrange
>    // the equation so we don't have to do any division
>    // subs g(gradient) for yInc/xInc gives us.....

>    // y(xInc) = x(yInc) - c(xInc)

>    // these are calculated below

>    int cxInc = ( (m_ptFrom.y*xInc) - (m_ptFrom.x*yInc) );
>    int yxInc = (point.y*xInc);
>    int xyInc = (point.x*yInc);

>    // these are to give us a small buffer area around the
>    // line so you don't have to click right on the line

>    int cxIncLo = cxInc - 2000;
>    int cxIncHi = cxInc + 2000;

>    // I don't know why 2000, but it seems to work.

>    // then the equation

>    if (yxInc > (xyInc + cxIncLo) &&
>        yxInc < (xyInc + cxIncHi) )
>    {
>        return TRUE;
>    }
>    else
>    {
>        return FALSE;
>    }

>} // end


>>yes but no...

>>Rgn are good if you want to know if the user clicked exactly on the line,
>>but not around the line... (and it become stranger with a set of line
>>segment...). So if you have a better solution it would be good ;-)

>>Tenebrax

Joseph M. Newcomer [MVP]

Web: http://www3.pgh.net/~newcomer
MVP Tips: http://www3.pgh.net/~newcomer/mvp_tips.htm


Fri, 25 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....

Quote:
> Note also that in the region-hit-point test method, there is nothing
> that says you have to draw the path with the same-size pen as you drew
> the line or curve; if, instead, you draw it with a wider pen (your
> buffer zone size), then the region hit test should do the job.

GOOD!!!!! Now I know why people call you expert... and why they call me
newbie ;-)...
That's THE easier way (cause it works with quite everything...)... I'll play
with it... really thanx !!!

Tenebrax - newbie of the newbie...



Fri, 25 Oct 2002 03:00:00 GMT  
 MFC Line drawing and selection problem.....


Fri, 19 Jun 1992 00:00:00 GMT  
 MFC Line drawing and selection problem.....
It is well over 20 years old now; I remember when it first came out,
and it was one of the coolest algorithms we'd seen. There was
Warnock's algorithm, and another that came out a couple months before
or after, which was equally cool. You might try the back-issue index
at www.acm.org, I think they were both Communications of the ACM
(CACM) articles. The divide-and-conquer technique is fairly well
documented in the literature; I haven't written one in C, although I
wrote one in the mid-1980s on a machine long forgotten in a language
virtually unknown, and all I have is a printed listing somewhere in
fifty boxes of archives.

I don't know if you saw my other post, but there is no reason to use
the region technique on the same width line as you drew; draw a wider
line when computing the region!



Quote:
>yes but no...

>Rgn are good if you want to know if the user clicked exactly on the line,
>but not around the line... (and it become stranger with a set of line
>segment...). So if you have a better solution it would be good ;-)

>Tenebrax

Joseph M. Newcomer [MVP]

Web: http://www3.pgh.net/~newcomer
MVP Tips: http://www3.pgh.net/~newcomer/mvp_tips.htm


Fri, 25 Oct 2002 03:00:00 GMT  
 
 [ 18 post ]  Go to page: [1] [2]

 Relevant Pages 

1. CToolBar selection state drawing problem!!

2. CRichEdit line selection - line index

3. problem drawing dashed line in NotXorPen mode

4. Line Drawing Problem...

5. Problem drawing a dashed line

6. Help - Problems with Drawing an MFC ActiveX control inside on ATL compsoite control

7. Problems with Drawing an MFC ActiveX control inside on ATL compsoite control

8. Owner Draw CListView not showing selection box

9. MFC Drawing With Linked Lists -- Problem

10. How to draw selection handles

11. How to draw selection handles

12. Problems with Direct Draw and MFC

 

 
Powered by phpBB® Forum Software