|
One way to achieve the desired result does not involve 'drawing' at all.
Make use of Control.MouseHover[^]. Of course this means that you would need to have some form of collection containing the coordinates of the various rooms/asset owners to check against the mouse coords.
Henry Minute
Do not read medical books! You could die of a misprint. - Mark Twain
Girl: (staring) "Why do you need an icy cucumber?"
“I want to report a fraud. The government is lying to us all.”
Why do programmers often confuse Halloween and Christmas?
Because 31 Oct = 25 Dec.
|
|
|
|
|
Here is a technique that often works well:
- have your image, shown to the user;
- have a second image (or a 2D array) of the same size, containing nothing but an item code for each pixel; so it could hold a value of 1 or RGB(1,0,0) for all pixels belonging to room 1, etc.; this "shadow" image is not shown to the user at all.
- have an array or list of items holding the description of each room.
While the mouse hovers the real image, use its (relative) position to do a GetPixel in the shadow image at the same location, that yields the room index (or a special value for none), then fetch the room description from the array/list. You can then:
- paint a highlighted outline of the room on top of the Control that shows the floor plan;
- stuff relevant information in the tooltip.
Remarks:
1. if your image is large, you might create a shadow image at a smaller scale, say 1/4.
2. filling the shadow image can be handled by code, based on the room description; it would then need coordinates of course.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Thanks for the reply!
Ok that sounds like a great idea but I'm having a little difficult time following you. I have not worked much with graphics in that way. Would it be possible to point me to a article I could read that would help in this area?
As to your remarks, my image is large I would say. It's size is 800 x 600.
Edit:
I found an article I think: Image Processing for Dummies with C# and GDI+ Part 1 - Per Pixel Filters[^]
I'm reading it right now.. will let you know if this helps me towards your soltuion
modified on Wednesday, May 26, 2010 10:46 AM
|
|
|
|
|
I don't have a link to such thing.
As for size, it basically depends on how accurate you want your hovering response to be; if the walls are 5 pixels thick, then a scale of 1/4 would be adequate. If walls are only 2 pixels, maybe you want actual size.
BTW: the shadow image helps in mapping the mouse position to the room number; you can of course do without, simply by scanning your room list and checking for "room contains point"; the shadow image comes in handy when you have lots of different rooms (performance), or oddly shaped ones (such as corridors) that make the containment test rather tedious.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I posted above on the article I'm reading that will hopefully help with GDI..
As for performance we have rooms of different shape and sizes and there are MANY rooms lol.
|
|
|
|
|
Since he would have to create the shadow image anyway, and this is in human time rather than real time (being a response to a mouse action), I would maintain each room as a Region, and do the hit test on that - it is probably easier to read IMO!
foreach (Region r in myRooms)
{
if (r.IsVisible(pt))
{
...
}
}
Did you know:
That by counting the rings on a tree trunk, you can tell how many other trees it has slept with.
|
|
|
|
|
yes, regions sound fine, it all depends on where the data is coming from; it might be hard to initialize the regions, one or a couple of rectangles per room (even overlapping ones) could be easier; see my other reply below.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Luc Pattyn wrote: ne or a couple of rectangles per room (even overlapping ones)
Is pretty much what I was thinking - then just use Region.Union so you are only working with one object to represent a room outline. But if you do have curved walls, you can handle that as well...
Did you know:
That by counting the rings on a tree trunk, you can tell how many other trees it has slept with.
|
|
|
|
|
the main issue is you have to enter the data in the system; which may require some digitization, or manually measuring and entering the coordinates for a lot of points. Regions are fine for computers, less so for humans.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I have actually never messed with a "Region". I'm going to have to research what it is and what it does in a few
|
|
|
|
|
Ok I think I understand how I am supposed to scan each pixel. From that article I see how I can change the color as well. Now what I am wondering is how do I actually tell the location of the pixel to what I am looking at? Basically how do I find the bounderies for each room so I can keep an array saying that "These pixels belong to room 1", "these pixels belong to room 2"?
|
|
|
|
|
Lets assume you have lots of rooms, and/or strangely shaped ones. So a shadow image is the recommended way.
There are two ways to get one:
1.
by hand, which means someone uses paper and pencil, or Photoshop, or whatever he feels comfortable with; what is required is the outline of the separate rooms, then each outline filled by a distinct solid color
(you could use red, green, blue, yellow, etc rather than RGB(1,0,0), RGB(2,0,0), ... as these cannot be told apart by the human eye.
2.
from digital data, which you obtain by looking at the real image, measuring relevant points, etc (maybe using a digitizer); and then you store them in a data structure describing your rooms; then a piece of code creating the shadow image. Of course, if you have the digital data you can always argue you don't need the shadow image any more, as drawing it and hit-identifying it aren't very much different.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Sorry if I'm sounding dumb but let me see if I have this right....
So you are suggesting take the image have of the floor plan.. outline each room in a different color? When I do this I can then scan each pixel, determine if it matches a certain color and map the room. So if I outline room 5 (or fill in) as red and scan for red, each RED pixel I find store that point as Room 5.
Then when I get to theu ser point.. I use the mousehover event to get the x,y location of the cursor and somehow find the pixel which can give me the room nubmer to display data about?
|
|
|
|
|
there are many ways to get this done, the best way depends on your starting position. Si please first clarify the situation you are in.
1.
the floor plan, is it an image, a picture, or a drawing? and do you have it in print, or is it strictly digital so printing/scanning is unnecessary?
2.
and then the virtual floor plan, the one that will become the shadow image. How would you like to make it? by graphic art operations on the actual floor plan? by writing some code?
3.
and what quantities are involved? is it one or two floors of your house? or all the floors of all the buildings your corporation is using all around the world?
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
1. This is an image that was given to us by the Nabholz construction of our floor plan. It includes doors, stairways, closets, etc.. It is very precise, so if a room had a little curve to it, so does the image. I only have a jpg file.. no actual paper. I could always print it out, then scan it back in.
2. I think the issue is I've never done anything like this. So I'm a beginner. Am I an artist? No. If it is possible to program it I guess it would be easier for me to stick with that.
3. Just this one floor for this one building.
I just wanted to point out this wasn't requested of me.. just an idea I had so I could try to accomplish it to learn something. So if it turns out I should be doing something different that is ok.
You are always welcome to view the floor plan if you want me to send to you so you might have a better idea?
Ok so I set this up on the picture box and this:
private void picFloorPlan_MouseMove(object sender, MouseEventArgs e)
{
lbStatus.Text = string.Format("{0}x / {1}y", e.X, e.Y);
}
This give me the X and Y coordinates of the cursor. So here is exactly what I'm confused on.. Lets say I used my cursor and found 156x / 200y. How do I find that exact location by pixel and color it? Not only that but I'm guessing I would get a range of coordinates and somehow color that range and add each value to an array stating that it is Room 1 or whatever. Another thing is how exactly do I translate the pixel to coordinates? Can you get the specific pixel by coordinate?
|
|
|
|
|
OK, so you have the real image as digital artwork, and you did not mention having a digitizer. This is what you could do:
- choose an app you feel comfortable with, that lets you draw straight lines as well as freehand lines, on top of (without including) an existing image. A lot of apps work with layers, where you can see several layers at once, modify only one layer at a time, and finally save the superposition of any set of layers you choose.
- open said app, let it display the floor plan in one layer; now put an empty layer on top of it, and in that layer, paint the outline of a single room in black. Make sure it is a closed figure.
- when done, fill it black; then fill it again in red. (I have chosen to work in black for best contrast, then switch to the final color; you could also directly work in the final color).
- repeat for a second room, but choose a different final color.
- do a couple of rooms; don't do them all before everything turns out satisfactorily!
- now save the one layer you have drawn in an uncompressed format, say GIF (you don't want the colors to get damaged at all).
Hint: perform several saves while doing this, into different files; you may want to return to an earlier situation when something went wrong...
Now create (part of) your app, temporarily show the shadow image instead of the real one. Mouse over room 1 and display the RGB color values you are getting (they should be absolutely constant within each single room).
Use this tool to sample the colors you need to create your data structure; it could be something like:
class Room {
string name;
string comment;
Color color;
public Room(string name, string comment, int R, int G, int B) {
this.name=name;
this.comment=comment;
this.color=Color.FromRGB(R,G,B);
}
}
class MyApp {
void CreateRooms() {
List<Room> rooms=new List<Room>();
rooms.Add("Kitchen", "check smoke alarm once a year", 255, 0, 0);
rooms.Add(...);
...
}
...
void Image_MouseMove(...) {
Color color=shadowImage.GetPixel(e.X, e.Y);
Room room=null;
if (rooms==null) CreateRooms();
foreach(Room r in rooms) if (r.Color == color) room=r;
if (room!=null) {
...
}
}
}
that is the zest of it. It probably needs syntax fixes and refinements, but should get you started.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Interesting thread Luc. I'm about to embark on a utility similar to this so your answers here will probably save me many hours of work!
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
Thanks Dave.
Will this turn into a CP article?
If so, do you want any help?
Cheers.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
modified on Wednesday, May 26, 2010 2:38 PM
|
|
|
|
|
Luc Pattyn wrote: Will this turn into a CP article?
It depends on how embarassing the code turns out to be I can do basic drawing with no problems but full on graphics stuff is new to me I have to admit. I'm thinking about using this as a possible reason to take the plunge into WPF - maybe! It may be a better tool for the job Any opinion?
Luc Pattyn wrote: If so, do you want any help?
A very kind and flattering offer - if it starts off OK then I will take you up on that. Thank you!
DaveIf this helped, please vote & accept answer!
Binging is like googling, it just feels dirtier. (Pete O'Hanlon)
BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)
|
|
|
|
|
I have no experience with, and no personal opinion on WPF. All related comments in the Lounge made me decide to stay away from it until it, and the tools it requires, become somewhat decent and stable. Not sure that has happened yet.
And I couldn't comment on what would be best for your app, as I am not familiar with its requirements or functionality, other than that you want to do some point-and-clicking. Which in itself can be served well by GDI+.
FWIW: sooner or later, I'll have to give in, and learn WPF. At such time, I'll be much interested in tackling the same problem twice, and compare the practical aspects of both WPF and GDI+.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
Ahhhhh now I see where you are. I gave that a try and it worked. So basically I have a Bitmap that I set when the form loads to the picture with the color squares/other shapes.
When the mouse moves over the image shown it ask the Shadow image for the color it has.. if it matches a specific room then that is when it shows the information.
You - are - a - genius
I was trying to go a hard way around i guess.. or the impossible way i dunno.
So let me ask you this.. is it possible to highlight that area? Since each room will have a specific color assigned to it, and the mouse moves over it.. is it possible to some how highlight that room with a opacity on the windows form?
Thank you so much for what you helped me out with. I understand completely what you were tryign to tell me since you posted the steps. Can't believe I didn't see this earlier
|
|
|
|
|
Yes, you have a real and a shadow image; you show the real one, but virtually you walk the shadow one so you get room identification almost automatically.
To highlight a room, you could do one of several things:
- replace the entire picture by a new one which you created manually (so N rooms takes N+1 pictures plus a shadow image); conceptually simple, lots of unrewarding work.
- replace the entire picture by a new one which you calculate on the spot. It could consist of the original pixels unmodified except for the ones that are inside the room, you could change their visible color and/or brightness; for a black-and-white floor plan, you might want to highlight the "current" room using a yellowish local background. It probably takes a couple of tricks to get that to work swiftly; you can't do a full 600*800 GetPixel/SetPixel loop fast enough, but you could do a two-image flood fill (scan the shadow, modify the visible image). Alternatively, you could extract each room once, from the shadow image; so you get separate room images, which tell you where the highlight should happen. If you make all room images the same highlight color, all you need is painting two images on top of each other: the real one, and the current room.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I think the first one is the most work but would be most likely what I know to do. Because there really isn't anything specifying the size and shape of the room. There is just the color of it.
So when the mouse hovers it gets the room number from the shadow image (by the color) and replace the visible one with a new 800x600 image with just that room highlighted.
Have you ever attempted this before? I'm wondering if you would see the whole form flash or if it will actually look like the room just highlighted
|
|
|
|
|
splitting the shadow image into separate rooms is easy, as each room has its pixels in a different color.
it would be rather slow, however it needs to be done only once; so your app could do it once, at startup, in a background thread; or do it just-in-time and cache them; or you could write (the same) code to do it beforehand, and ship all the images with the app, possibly as embedded resources.
I haven't done this recently; I have done similar things in the past though. And I would see no flashing whatsoever, as I would probably use double-buffering, and the two images are very similar anyhow; where they differ, they do so on purpose. One should take care not to change anything as long as the current room does not change.
Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]
I only read formatted code with indentation, so please use PRE tags for code snippets.
I'm not participating in frackin' Q&A, so if you want my opinion, ask away in a real forum (or on my profile page).
|
|
|
|
|
I've been working on this and everything is going really well except one thing.. some colors are coming up different from photoshop vs when deployed in the application.
One color I chose is a redish color..
In photoshop it shows:
R= 253
G= 54
B= 0
But when I display the color in my application it shows as
R= 253
G= 29
B= 0
which is giving different colors? Any idea why? I saved it as a GIF format as you suggestde
|
|
|
|
|