Edit:
Simple code I used to solve the problem in case anyone is interested (thanks to Fredrik):
int windowOverlap(Rectangle rect1, Rectangle rect2)
{
if (rect1.IntersectsWith(rect2))
{
Rectangle overlap = Rectangle.Intersect(rect1, rect2);
if (overlap.IsEmpty)
return overlap.Width * overlap.Height;
}
return 0;
}
Original Question:
I'd like to know a quick and dirty way to check if two rectangles overlap and if they do calculate the area of the overlap. For curiosities sake I'm interested in the case where 1) all the lines in both rectangles are either vertical or horizontal or 2) the general case for any two rectangles, but the only answer I really need is case 1.
I'm thinking along the lines of:
double areaOfOverlap( Rect A, Rect B)
{
if ( A.Intersects(B) )
{
// calculate area
// return area
}
return 0;
}
For A.Intersects() I was thinking of using the separating axis test, but if the rectangles have only horizontal and vertical lines is there an even simpler (faster) way to check?
And for calculating the area where they intersect is there an quick way to do it if the rectangles only horizontal and vertical lines?
Finally, this is unrelated to the question but I'd appreciate any advice someone may have on a good book / webpage where I could review the math for computer graphics. I've been out of college for a while and feel like I'm forgetting everything :)! Anyone else have that problem?
( NOTE: I found this question different than this which seems more complicated and doesn't directly answer the question. )
Maybe I misinterpret your question, but doesn't the Rectangle.Intersect method do the job? It returns the intersecting area, and then you can easily calculate the area of it.
Sounds like basic Collision Detection. Have you looked at this page on Wikipedia?
Mike
edit: Fredrik make his response at the same time I made this one, his answer got my upvote ( :
Related
I want to implement this function to divide an angle but my math knowledge is very limited so I need help.
In practice and in programming only the lengths of the horizontal or vertical lines are available and easy to calculate.
my question is it possible to make this calculation with only one data
WZ which is horizon line
Short answer: No.
Long answer:
If XY == YZ:
bisected = arcsin(YZ/(YZ^2+WZ^2))
If XY != YZ:
bisected = 1/2*(arcsin(XY/(XY^2+WZ^2))+arcsin(YZ/(YZ^2+WZ^2)))
You'll need to know at least XZ and WZ to calculate the bisected angle.
Thanks for replying.
Yes it's easy to calculate it with the trigonomic function... since WZ is a horizontal line so by selecting any arbitrary point on WX to find the acrtan then divide it by 2
arctan(tangent of any point on WX)/2
I want to solve it with linear algebra and find the equations of the lines
My goal is to detect the different regions within a simple drawing constructed of various lines. Please click the following link to view a visual example of my goal for clarification. I am of course able to get the position of the drawn lines, but since one line can cross multiple 'regions' I don't think this information alone will be sufficient.
Any ideas, suggestions or points to other websites are welcome. I am using C# in combination with WPF - I am not certain which search words might lead to an answer to this problem. I did come across this shape checker article from AForge, but it seems to focus on detecting shapes that are already there, not so much on regions that still have to be 'discovered'. As a side note, I hope to find a solution that works not only with rectangles but also with other types of shapes.
Thank you very much in advance.
Update:
foreach (Line canvasObject in DrawingCanvas.Children.OfType<Line>())
{
LineGeometry lineGeometry1 = new LineGeometry();
lineGeometry1.StartPoint = new Point(canvasObject.X1, canvasObject.Y1);
lineGeometry1.EndPoint = new Point(canvasObject.X2, canvasObject.Y2);
if (canvasObject.X1 != canvasObject.X2) {
foreach (Line canvasObject2 in DrawingCanvas.Children.OfType<Line>()) {
if (canvasObject.X1 == canvasObject2.X1 && canvasObject.X2 == canvasObject2.X2 &&
canvasObject2.Y1 == canvasObject2.Y2 && canvasObject.Y2 == canvasObject2.Y2) {
return;
// prevent the system from 'colliding' the same two lines
}
LineGeometry lineGeometry2 = new LineGeometry {
StartPoint = new Point(canvasObject2.X1, canvasObject2.Y1),
EndPoint = new Point(canvasObject2.X2, canvasObject2.Y2)
};
if (lineGeometry1.FillContainsWithDetail(lineGeometry2).ToString() != "Empty") {
//collision detected
Rectangle rectangle = new Rectangle {
Width = Math.Abs(canvasObject.X2 - canvasObject.X1),
Height = 20,
Fill = Brushes.Red
};
//rectangle.Height = Math.Abs(canvasObject.Y2 - canvasObject.Y1);
DrawingCanvas2.Children.Add(rectangle);
Canvas.SetTop(rectangle, canvasObject.Y1);
Canvas.SetLeft(rectangle, canvasObject.X1);
}
}
}
}
I have experimented with the following code - to give you an impression of how I tried to tackle this problem. Initially I thought I had found a partial solution, by checking for collision between lines. Unfortunately I just created a second line of each line (which of course collided 'with itself'). After I added a simple if check (see below) this no longer occurs, but now I don't get any collisions anymore.. so will probably need a new technique.
Update 2:
After some more digging and searching the internet for solutions, I have a new potential solution in mind. Hopefully this can also be of use to anyone looking for answers in the future. Using a flood-fill algorithm I am able to 'fill' each region with a specific color - much like the paint bucket tool in an image editing application. Summarized, this done by taking a 'screenshot' of the Canvas element, starting at a certain pixel and expanding over and over until a pixel with a different color is found (these would be the lines). It works pretty well and is able to return an image with the various regions. However - my current problem is accessing these regions as 'objects' in C#/WPF. I would like to draw the regions myself (using polyobject or something similar?) - making it possible to use the objects for further calculations or interactions.
I have tried saving the position of the smallest and largest X and Y positions in the FloodFill algorithm after each pixel check, but this makes the algorithm work very very slow. If anyone has an idea, I would love to know. :)
I have an RGB image.Suppose say I have two circles in it.I want to know which one is filled and which one is not.I followed the following steps:
-imported the image as Bitmap
-converted into grayscale and used CannyEdgeDetector filter to find the edges. I get the following image
circle containing the letter "D" gives two edges, where as I need only one circle edge. Secondly, how do I find out which circle is filled and which one is not.
For the MCQ answers sheet, it might be easier to go by positions of the circles.
Just compare stock images of the clear, circled A, B, C and D's to the scanned images and see which differ the most. A simple darkness summation might be enough.
Also: Comparing the circles against each other might be useful too to compensate for a bad/dark/light scan or smudgy paper.
For special cases if the test isn't absolutely sure I'd probably pass it to a human being for further investigation. E.g., when you allow students to undo an answer by circling their second guess or when a student decides to make a real mess by using a bad eraser.
Final tip: make sure you do not accept answers that have the correct circle filled; make sure the other circles are clear at the same time so students can't cheat by filling all circles. (Some professors use a paper mask that overlays all bad answers so they can quickly spot unmarked correct answers. But if the student just marks all answers this fails big time.)
I would not know any "formal" algorithm matching your criteria. I would also doubt that you would find any.
When you say the circles are "darkened", this can be interpreted as this: "Many pixels (above a population threshold) would be black, or at least dark (above a colour threshold).". Based on known circle and radius, I would follow this approach (written in pseudocode but I suppose you get the meaning):
//define thresholds
colourThreshold=...
populationThreshold=...
centerPoint = getCircleCenter();
radius = getCircleRadius();
darkPixelsCount = 0;
for(x=centerPoint.X-radius;x<centerPoint.X+radius;x++){
for(y=centerPoint.Y-sqrt(abs(radius^2-(x - centerPoint.X)^2));centerPoint.Y+sqrt(abs(radius^2-(x - centerPoint.X)^2));y++){
if (image(x, y) > colourThreshold){
darkPixelsCounter++;
if(darkPixelsCounter > populationThreshold){
//If you reach this point, circle has been darkened
return;
}
}
}
}
//If you reach this point, circle has not been darkened
return;
I don't know if it is efficient, or if there is a more elegant way to do it. I suppose you could play with performance and accuracy by moderating the thresholds.
Hope I helped!
Perform blob detection, with a pixel count
or even simpler count the black pixels
or even simpler and faster, take middle line and count how often it switches from white to black
I don't even know how to describe what I want, but here goes. Assume I have 3 textboxes, and I enter some colour hex code in the first one, I want to apply a black layer on top of it, and have the opacity set to 50% and get the resulting colour in the second text box. Same thing, but with white on the third one.
Let me explain: consider this image below:
In Photoshop, I have the base layer which is sort of sky blue in colour. I create two layers on top of it, one with black, one with white but both have an opacity of 50%. Now, I can use the colour picker (I) to simply select the two wanted colours.
I am having to do this an insane amount of times so I was wondering if I could produce it programatically.
I know, Ideally I should have tried out something, then give out the code which isn't working.. but this has stumped me enough that I don't even know where to start. The closest thing I've seen is Kuler so I think it is possible in flash at least, but then again, I don't know where to start.
Can you guys please point me in the right direction? Ideally, this would be so much better if it's doable in jQuery, but I have looked around and couldn't find anything quite like it. I am not asking for a working solution, just a nudge in the right direction.
If you have any questions, please ask.
Technology is not important to me, solution is - I am most comfortable with c# (at least I like to think I am) but I am a beginner in php, flash. Jquery, I am good at it with most stuff (well, who isn't?) - Whatever works is good to me. Php and Flash, I learnt it as a hobby just to familiarize myself.
Many thanks.
So I can get close, but not exactly your results, which I think is a side effect of .NET using a number in the range 1..255 for alpha when creating a color.
But nonetheless, I think this pretty much does what you want:
public class ColorUtility
{
private Color color;
public ColorUtility(Color original)
{
this.color = original;
}
public Color GetTransformedColor(Color overlay)
{
using(var bitmap = new Bitmap(1,1))
{
var g = Graphics.FromImage(bitmap);
using(Brush baseBrush = new SolidBrush(this.color))
{
g.FillRectangle(baseBrush,0,0,1,1);
}
using(Brush overlayBrush = new SolidBrush(Color.FromArgb(127,overlay)))
{
g.FillRectangle(overlayBrush,0,0,1,1);
}
return bitmap.GetPixel(0, 0);
}
}
}
usage:
var startColor = ColorTranslator.FromHtml("#359eff");
var util = new ColorUtility(startColor);
var blackOverlay = util.GetTransformedColor(Color.Black); // yields #9aceff
var whiteOverlay = util.GetTransformedColor(Color.White); // yields #1b4f80
Close to your desired results, but not exactly.
EDIT: If you change the alpha value to 128 in the utility you get
Black: #9acfff
White: #1a4f7f
This might be closer to what you want, but its still not exact.
I know I am late for the party, just wanted to show another way of doing it.
There is a jquery color plugin for this, I have never really used this, but there is a function that looks like it does what you want.. xColor is the plugin you are looking for.. if you go the combination section you will see that it says that it does what you want.
I just tried a sample on jsfiddle but the results are in line with Jamie's amazing answer. this gives out the same result colors as that of Jamie's code. so you can use either I guess.
So... What's the problem to just write what you exactly said using technology you know best? 3 boxes with colors, input for opacity percentage and output as resulting mixed colors. (I can write it on flash, but I'm not sure if prividing the whole program is appropriate on this site.)
If you don't know how to mix colors with opacity, this link should help:
http://www.pegtop.net/delphi/articles/blendmodes/opacity.htm
I have a set of points, drawn by the user. They will be drawing around some objects.
I need to somehow turn this set of points into a shape, so I can find the area to detect collisions.
An image will clarify:
Set of points represented as shape http://www.imagechicken.com/uploads/1277188630025178800.jpg
.
The best idea I have had so far involves iterating over every pixel determining if it is 'inside' or 'outside' the shape, but that would be horribly slow, and I'm not even sure how to do the determining 'inside'/'outside' bit...
Any hints? I am using .NET (C# and XNA) if that helps you help me!
You can think of your shape as an union of several shapes each of which is a simple closed polygon.
the check for every object if it is inside any of the polygons in the following manner:
All dots connected by lines - each line has an equation defining it.
For every object - build an equation for a line passing through this object.
now - for each object equation you need to check how many lines (those between the dots) intersects this object equation - but count only the intersection points that are in the rage between the two dots (and not in the rest of the line outside the two dots) and only the intersection points that are in one side of the object (pick a side - doesn't matter).
If the count is even - the object is outside the shape - otherwise it is inside.
Just a precursor to anything I will say, I have no experience in this field, this is just how I would go about the problem.
A tactic a lot of games use for this is known as Hit Boxes. It is much easier to detect if a point is inside a square than any other figure. But this doesn't give you an exact collision, it could be right outside your desired object.
I've seen Collision 'Bubbles' used before. Here is a link I found for you. This explains the use of Collision Bubbles in the console game Super Smash Brothers.
Given a point, the distance formula, and a radius, you can easily implement collision bubbles.
To take it even one step forward, I did a little bit of research, I saw a nifty little algorithm (more advanced that the top two suggestions), the "Gilbert-Johnson-Keerthi Collision detection algorithm for convex objects." Here is a link for ya. The implementation provided is written in D. If your working in C# it shouldn't be too hard to translate (I would highly suggest digesting the algorithm too).
Hope this gives you some direction.
Well I got it working thanks to some help on another forum.
I used the GraphicsPath class to do all the hard work for me.
This is what my method ended up looking like:
public bool IsColliding(Vector2 point)
{
GraphicsPath gp = new GraphicsPath();
Vector2 prevPoint = points[0];
for (int i = 1; i < points.Count; i++)
{
Vector2 currentPoint = points[i];
gp.AddLine(prevPoint.X, prevPoint.Y, currentPoint.X, currentPoint.Y);
prevPoint = currentPoint;
}
gp.CloseFigure(); //closing line segment
return gp.IsVisible(point.X, point.Y);
}
Thanks for your suggestions both of you