none
How can I prevent Line from crossing over the rectangle?

    Question

  • Hello Everyone,

     

    I am working on something where I allow the user to drag shapes onto drawing panel and connect them through lines.

    The shapes and lines can be grabbed using mouse and moved.

    My requirement is that line should never cross the shapes. I tried doing this through conditions like checking X Y coordinates on mouse move but

    soon found it to be tedious and error prone.

    Is there any way that I let WPF take care of this on its own. Like some events that I can attach so the moment line comes over the shape it relocates back to previous location..

    I have seen something like this in a coupe of examples but they use XAML file and I don't have a XAML in my application, need to do everything through code.

     

    Thanks in advance :)

    Tuesday, October 12, 2010 4:52 AM

Answers

  • Hi Vijay and Yves,

    @Yves - yes, I presume that I've understood what Vijay is after. It's only that I have next to no time at all for the forums presently, hence my late reply.

    @Vijay - I haven't tried any of the code that comes with the article that Yves mentioned (actually I have only skimmed over the article). I second Yves' opinion that there won't be any "easy" (or built-in) way to accomplish what you want. However, I would assume that you could constantly utilize the MouseMove event in order to generally monitor as to whether your resulting connector-line would overlap any of your two rectangles. In order to test that, you could use what I introduced in my blog (see the RectAndLineIntersectionPoint method) which you would have to call for each of your rectangles' sides separately (just as described in the blog post). Not only would that method give you an indication of whether or not there is any intersection, but it would also give you the exact point which, in turn, could be used as the new start- or end-point of your line. This would result in the line ending before the shape. Alternatively, the method could serve as the trigger after which the user's moving of objects would be stopped due to being "invalid" (not sure whether I understood your concern there).

    Of course, you'd also have to consider your pins, but if I was doing this, I'd simply assure that the line's ZIndex is lower than that of the pin so that the line would be underneath them.


    Cheers,
    Olaf
    http://blogs.intuidev.com
    Thursday, October 14, 2010 11:51 AM

All replies

  • Hi Vijay,

    if the number of shapes/lines that exist on your panel (which I guess is a Canvas) isn't generally infinite, I'd simply assure that the lines' ZIndex is always lower than that of any other shape.


    Cheers,
    Olaf
    http://blogs.intuidev.com
    Tuesday, October 12, 2010 6:43 AM
  • Thank you for your reply Olaf. If my understanding is correct, ZIndex will simply put by lines behind the shapes (but they will still cross the shape). I don't want to do that, Lines are suppose to position themselves around the shape..
    Tuesday, October 12, 2010 8:20 AM
  • Hi Vijay,

    yes, by utilizing ZIndex the line would be there, but just not visible when a shape crossed it.

    I've only recently blogged about Animating objects along a path and connecting them with a line - maybe that could provide a bit of help. There, the final outcome is two shapes whose perimeters are constantly being connected by a line. I only did this for a rectangle and an ellipse though, not for i.e. a Path (which could get quite complicated). However, if do not have the need to constantly connect the line between a dynamic point on the shapes' parameters but rather a certain one (such as i.e. the top left), it would be quite easy.

    From what I understand from your original question though, I'm afraid that you'll probably really need to go the hard way and either calculate the closest connecting points on your two shapes' perimeters or (a bit simpler) connect both shapes' center points and reduce the line so that it ends in the respective object's perimeter (in which case my math might help to get you started).


    Cheers,
    Olaf
    http://blogs.intuidev.com
    Tuesday, October 12, 2010 8:38 AM
  • I have already seen your code :) during my research for an approach to do this. Great visuals :)

     

    Let me put my question in a bit more detailed way.

    Suppose there are two rectangles on canvas.

    User will click on the connecting pin of the first box (Mouse down event), I capture the center of this pin and assign it as the first point to my poly-line collection.

    On mouse up on the second rectangle I assign the center of this rectangle's pin as the last point. I need to keep the lines straight always (that's why poly-line) so I draw something like this:

     

     

    First Point__________2

                                 |

                               3|________________Last Point

     

    by doing this:

    x1 = First Point.X

    Y1 = First Point.Y

    X2 = (X4 + X1) / 2

    Y2 = Y1

    X3 = X2

    Y3 = Y4

    X4 = Last Point.X

    Y4 = Last Point.Y

     

    Now when I move second shape to left the line will cross the first shape. Can I figure out this through an event or let WPF take care of it somehow..!

    Tuesday, October 12, 2010 9:03 AM
  • Any ideas?
    Thursday, October 14, 2010 5:26 AM
  • Hi vijaykamat,

    I have read Olaf's blog, amazing work, and I wonder whether Olaf understands you right or not.

    I am afraid there is not much straightforward way to handle the intersection of two Visuals in your case. Could you change the position of the box's pin? If it's the case, you could judge the relationship of two boxes and replace the pins. Assuming that the first box’s pin is at right and the second left, when the second box is at left of first box, you may replace the pin of first box to its left edge and second box’s to right. Otherwise you could use Olaf’s perimeter connected line to your polyline’s start segment and last segment.

    If I misunderstand you, could you please supply a ready-to-use demo to show the case?

    And I recommend you read this article http://www.codeproject.com/KB/WPF/WPFDiagramDesigner_Part3.aspx. You may find some ideas from it.

    Have a good day!

    This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. Microsoft does not control these sites and has not tested any software or information found on these sites; therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information found there. There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

     

    Best regards,

    Yves


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    Thursday, October 14, 2010 11:11 AM
    Moderator
  • Thank you for the article Yves.C.

    You have understood my problem correctly. But as you have suggested I cant change the location of pins :(

    The article is good.. what I am interested is in the method "UpdatePathGeometry()" for which unfortunately no code is available.

    If there is no way to handle the intersection of two Visuals I think I will have to code it my self..

    Thank you for your help :)

     


    Thursday, October 14, 2010 11:21 AM
  • Hi Vijay and Yves,

    @Yves - yes, I presume that I've understood what Vijay is after. It's only that I have next to no time at all for the forums presently, hence my late reply.

    @Vijay - I haven't tried any of the code that comes with the article that Yves mentioned (actually I have only skimmed over the article). I second Yves' opinion that there won't be any "easy" (or built-in) way to accomplish what you want. However, I would assume that you could constantly utilize the MouseMove event in order to generally monitor as to whether your resulting connector-line would overlap any of your two rectangles. In order to test that, you could use what I introduced in my blog (see the RectAndLineIntersectionPoint method) which you would have to call for each of your rectangles' sides separately (just as described in the blog post). Not only would that method give you an indication of whether or not there is any intersection, but it would also give you the exact point which, in turn, could be used as the new start- or end-point of your line. This would result in the line ending before the shape. Alternatively, the method could serve as the trigger after which the user's moving of objects would be stopped due to being "invalid" (not sure whether I understood your concern there).

    Of course, you'd also have to consider your pins, but if I was doing this, I'd simply assure that the line's ZIndex is lower than that of the pin so that the line would be underneath them.


    Cheers,
    Olaf
    http://blogs.intuidev.com
    Thursday, October 14, 2010 11:51 AM
  • Dear Olaf,

    Thank you for RectAndLineIntersectionPoint . I am on it right away :)

    Friday, October 15, 2010 5:15 AM