问题
I have an image in UIImageView. I have drawn lines on the image sucdcessfully.Now I want to remove that specific line on which user will perform a long press gesture. how can I do that ? my code is :
{
// gets the location in the form of (x,y) coordinates
CGPoint location=[sender locationInView:imageView];
// convetrs the location relative to the image
CGPoint contextLocation = CGPointMake(location.x*imageView.image.size.width/imageView.frame.size.width, location.y*imageView.image.size.height/imageView.frame.size.height);
// converts the location point into NSValue
NSValue *imagePoint=[NSValue valueWithCGPoint:contextLocation];
// Adds the image into NSMutable Array
[imageLocations addObject:imagePoint];
// color of line
UIColor * linearcolor=[UIColor blueColor];
UIGraphicsBeginImageContext(imageView.image.size);
[imageView.image drawAtPoint:CGPointMake(0, 0)];
CGContextRef context=UIGraphicsGetCurrentContext();
// Brush widt
CGContextSetLineWidth(context, 3.0);
// Line Color
CGContextSetStrokeColorWithColor(context, [linearcolor CGColor]);
// Hard coded point for location 2
CGPoint location2=CGPointMake(300, 400);
CGContextMoveToPoint(context, contextLocation.x, contextLocation.y);
CGContextAddLineToPoint(context, location2.x, location2.y);
CGContextStrokePath(context);
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image=newImage;
}
回答1:
What you need to do is find the line pressed and remove it from the array of points you have and then redraw the whole image with the lines.
I guess the problem is in how to find the correct line:
Lets say you have a location L gotten from the gesture. Then what you need is to iterate through all the point pairs such as
for(NSInteger i=0; i< imageLocations.count.count-1; i+=2)
{
CGPoint T1 = [imageLocations[i] CGPointValue];
CGPoint T2 = [imageLocations[i+1] CGPointValue];
}
Now you have points L, T1, T2. From here there are many ways to detect if the line is hit. What I like most is to first use a dot product to see if the press is near the line like so:
CGFloat dotValue = dot(normalized(T1-L), normalized(T2-L))
Find the procedures for the dot product and the normalization of a point online. Now the dotValue should be near -1 for the line to be hit. You should use something like if(dotValue > -.7f) continue; to remove all the lines too far from the press along the line.
Next is to actually find the line distance from the point. This is actually a Z component of a cross product:
CGFloat crossValue = fabsf(cross((L-T1), normalized(T2-T1)).z);
I know you have no Z component so use:
crossValue = A.x*B.y - A.y*B.x
So now that you have all this the pseudo code should be something like this:
CGPoint L;
NSInteger bestLineIndex = -1;
CGFloat bestLineDistance = 10000.0f; // something large
for (CGPoint T1, T2; NSInteger index)
{
dotValue = ...
if(dotValue < -.7)
{
crossValue = ...
if(crossValue < bestLineDistance)
{
bestLineDistance = crossValue;
bestLineIndex = index;
}
}
}
So in the end you have the index of your first line point which should be removed if not -1 (if -1 no line was found near the touch).
For line distance from a point using a cross product:
- (CGFloat)distanceBetweenPoint:(CGPoint)L andLineWithStart:(CGPoint)T1 end:(CGPoint)T2
{
CGPoint T1toL = CGPointMake(L.x-T1.x, L.y-T1.y);
CGPoint T2toL = CGPointMake(L.x-T2.x, L.y-T2.y);
CGFloat T2toLDistance = sqrt(T2toL.x*T2toL.x + T2toL.y*T2toL.y);
CGPoint T2toLNormalized = CGPointMake(T2toL.x/T2toLDistance, T2toL.y/T2toLDistance);
CGFloat zComponentOfCross = T1toL.x*T2toLNormalized.y - T1toL.y*T2toLNormalized.x;
return fabs(zComponentOfCross);
}
回答2:
It's simple. I add my code below as your question.
// gets the location in the form of (x,y) coordinates
CGPoint location=[sender locationInView:imageView];
// convetrs the location relative to the image
CGPoint contextLocation = CGPointMake(location.x*imageView.image.size.width/imageView.frame.size.width, location.y*imageView.image.size.height/imageView.frame.size.height);
// converts the location point into NSValue
NSValue *imagePoint=[NSValue valueWithCGPoint:contextLocation];
// Adds the image into NSMutable Array
[imageLocations addObject:imagePoint];
// color of line
UIColor * linearcolor=[UIColor blueColor];
UIGraphicsBeginImageContext(imageView.image.size);
[imageView.image drawAtPoint:CGPointMake(0, 0)];
CGContextRef context=UIGraphicsGetCurrentContext();
// Brush widt
CGContextSetLineWidth(context, 3.0);
**CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear);**
// Hard coded point for location 2
CGPoint location2=CGPointMake(300, 400);
CGContextMoveToPoint(context, contextLocation.x, contextLocation.y);
CGContextAddLineToPoint(context, location2.x, location2.y);
CGContextStrokePath(context);
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
imageView.image=newImage;
}
Hope this is helpful.Enjoy.
来源:https://stackoverflow.com/questions/27983655/removing-lines-from-uiimage-in-ios