I'm trying to create an application which draws angles every 3 taps by the user. Each tap creates the angle points and connects them.
This is quite simple to do. However, now i'm trying to make these angles editable and it gets substantially harder. When I finish my 3 taps and touchesEnded gets called, I add the three points into an NSObject subclass called segment which has three properties, firstPoint, secondPoint, and thirdPoint, and it stores precisely that.
I then add the 'segment' object into an array. Every time touchesBegan gets called, I get into a for loop for my array. If the tap is within 25px of any of the 3 CGPoints of the "segment" object, then I don't draw a new angle, I edit that angle.
As far as I know, at this point, there aren't any problems or errors thanks to you guys! I'm just checking for general improvements/simplifications keeping the current method i'm using. I wish I could give the bounty to everyone because you've all been so helpful!
This is my biggest project so far, and I would greatly appreciate some insight. It's a pretty good challenge if you're up for it and can handle it. Any help, at all, is IMMENSELY appreciated. If you can think of a better way to handle what i'm trying to accomplish, by all means please let me know!
Note: to draw, just tap/click on the screen.
Here is the most relevant code:
drawingsubclass.m
#import "SegmentDraw.h"
#import <QuartzCore/QuartzCore.h>
BOOL editing1 = FALSE;
BOOL editing2 = FALSE;
BOOL editing3 = FALSE;
BOOL erased = FALSE;
int radius = 35;
int handleSize = 20;
@implementation SegmentDraw {
UIImage *incrementalImage;
}
@synthesize first;
@synthesize second;
@synthesize third;
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setMultipleTouchEnabled:NO];
[self setBackgroundColor:[UIColor clearColor]];
first = CGPointZero;
second = CGPointZero;
third = CGPointZero;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
for (Segment *currentSegment in self.tapArray) {
int xDistance = abs(point.x - currentSegment.firstPoint.x);
int yDistance = abs(point.y - currentSegment.firstPoint.y);
int firstDistance = sqrtf(xDistance * xDistance + yDistance * yDistance);
int xDistance2 = abs(point.x - currentSegment.secondPoint.x);
int yDistance2 = abs(point.y - currentSegment.secondPoint.y);
int secondDistance = sqrtf(xDistance2 * xDistance2 + yDistance2 * yDistance2);
int xDistance3 = abs(point.x - currentSegment.thirdPoint.x);
int yDistance3 = abs(point.y - currentSegment.thirdPoint.y);
int thirdDistance = sqrtf(xDistance3 * xDistance3 + yDistance3 * yDistance3);
if (firstDistance <= radius) {
NSLog(@"First point matches");
editing1 = TRUE;
editing2 = FALSE;
editing3 = FALSE;
first = point;
second = currentSegment.secondPoint;
third = currentSegment.thirdPoint;
self.segmentBeingEdited = currentSegment;
[self setNeedsDisplay];
[self drawBitmap];
erased = FALSE;
return;
}
else if (secondDistance <= radius) {
NSLog(@"Second point matches");
editing2 = TRUE;
editing1 = FALSE;
editing3 = FALSE;
first = currentSegment.firstPoint;
second = point;
third = currentSegment.thirdPoint;
self.segmentBeingEdited = currentSegment;
[self setNeedsDisplay];
[self drawBitmap];
erased = FALSE;
return;
}
else if (thirdDistance <= radius) {
NSLog(@"Third point matches");
editing3 = TRUE;
editing1 = FALSE;
editing2 = FALSE;
first = currentSegment.firstPoint;
second = currentSegment.secondPoint;
third = point;
self.segmentBeingEdited = currentSegment;
[self setNeedsDisplay];
[self drawBitmap];
erased = FALSE;
return;
}
else {
editing1 = FALSE;
editing2 = FALSE;
editing3 = FALSE;
}
}
if (CGPointEqualToPoint(first, CGPointZero)) {
first = [touch locationInView:self];
}
else if (!CGPointEqualToPoint(first, CGPointZero) && CGPointEqualToPoint(second, CGPointZero)) {
second = [touch locationInView:self];
}
else if (!CGPointEqualToPoint(first, CGPointZero) && !(CGPointEqualToPoint(second, CGPointZero)) && CGPointEqualToPoint(third, CGPointZero)) {
third = [touch locationInView:self];
}
else {
//[self drawBitmap];
first = [touch locationInView:self];
second = CGPointZero;
third = CGPointZero;
}
[self setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
for (Segment *currentSegment in self.tapArray) {
if (editing1) {
editing2 = FALSE;
editing3 = FALSE;
first = point;
second = self.segmentBeingEdited.secondPoint;
third = self.segmentBeingEdited.thirdPoint;
//self.segmentBeingEdited = currentSegment;
if (erased == FALSE) {
[self drawBitmap];
// NSLog(@"YOU NEED TO ERASE.");
}
[self setNeedsDisplay];
return;
}
else if (editing2) {
editing1 = FALSE;
editing3 = FALSE;
first = self.segmentBeingEdited.firstPoint;
second = point;
third = self.segmentBeingEdited.thirdPoint;
//self.segmentBeingEdited = currentSegment;
if (erased == FALSE) {
[self drawBitmap];
// NSLog(@"YOU NEED TO ERASE.");
}
[self setNeedsDisplay];
return;
}
else if (editing3) {
// NSLog(@"It's editing time, yo");
editing1 = FALSE;
editing2 = FALSE;
first = self.segmentBeingEdited.firstPoint;
second = self.segmentBeingEdited.secondPoint;
third = point;
//self.segmentBeingEdited = currentSegment;
if (erased == FALSE) {
[self drawBitmap];
// NSLog(@"YOU NEED TO ERASE.");
}
[self setNeedsDisplay];
return;
}
else {
editing1 = FALSE;
editing2 = FALSE;
editing3 = FALSE;
}
}
if (!CGPointEqualToPoint(first, CGPointZero) && CGPointEqualToPoint(second, CGPointZero)) {
first = [touch locationInView:self];
}
else if (!CGPointEqualToPoint(first, CGPointZero) && !(CGPointEqualToPoint(second, CGPointZero)) && CGPointEqualToPoint(third, CGPointZero)) {
second = [touch locationInView:self];
}
else if (!CGPointEqualToPoint(first, CGPointZero) && !(CGPointEqualToPoint(second, CGPointZero)) && !(CGPointEqualToPoint(third, CGPointZero))) {
third = [touch locationInView:self];
}
else {
first = [touch locationInView:self];
second = CGPointZero;
third = CGPointZero;
}
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSUInteger index;
if (editing1 || editing2 || editing3) {
index = [self.tapArray indexOfObject:self.segmentBeingEdited];
Segment *datSegment = [self.tapArray objectAtIndex:index];
datSegment.firstPoint = first;
datSegment.secondPoint = second;
datSegment.thirdPoint = third;
}
if (!CGPointEqualToPoint(third, CGPointZero) && editing1 == FALSE && editing2 == FALSE && editing3 == FALSE) {
Segment *segment = [[Segment alloc] init];
segment.firstPoint = first;
segment.secondPoint = second;
segment.thirdPoint = third;
if (self.tapArray == nil) {
self.tapArray = [[NSMutableArray alloc] init];
}
[self.tapArray addObject:segment];
}
editing1 = FALSE;
editing2 = FALSE;
editing3 = FALSE;
erased = FALSE;
[self drawBitmap];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)drawRect:(CGRect)rect {
[incrementalImage drawInRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextSetLineWidth(context, 5.0);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
if (!CGPointEqualToPoint(first, CGPointZero)) {
CGRect rectangle = CGRectMake(first.x - 10, first.y - 10, handleSize, handleSize);
CGContextAddEllipseInRect(context, rectangle);
CGContextMoveToPoint(context, first.x, first.y);
if (!CGPointEqualToPoint(second, CGPointZero)) {
CGContextAddLineToPoint(context, second.x, second.y);
CGRect rectangle2 = CGRectMake(second.x - 10, second.y - 10, handleSize, handleSize);
CGContextAddEllipseInRect(context, rectangle2);
CGContextMoveToPoint(context, second.x, second.y);
}
if (!CGPointEqualToPoint(third, CGPointZero)) {
CGContextAddLineToPoint(context, third.x, third.y);
CGRect rectangle3 = CGRectMake(third.x - 10, third.y - 10, handleSize, handleSize);
CGContextAddEllipseInRect(context, rectangle3);
}
CGContextStrokePath(context);
}
}
- (void)drawBitmap {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
if (!incrementalImage) { // first draw;
UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
[[UIColor clearColor] setFill];
[rectpath fill]; // fill it
}
[incrementalImage drawAtPoint:CGPointZero];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextSetLineWidth(context, 5.0);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineJoin(context, kCGLineJoinRound);
if (editing1 || editing2 || editing3) {
// CGContextBeginTransparencyLayer(context, NULL);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextSetLineWidth(context, 6.0);
//CGContextSetBlendMode(context, kCGBlendModeColor);
if (!CGPointEqualToPoint(self.segmentBeingEdited.firstPoint, CGPointZero)) {
CGContextMoveToPoint(context, self.segmentBeingEdited.firstPoint.x, self.segmentBeingEdited.firstPoint.y);
if (!CGPointEqualToPoint(self.segmentBeingEdited.secondPoint, CGPointZero)) {
CGContextAddLineToPoint(context, self.segmentBeingEdited.secondPoint.x, self.segmentBeingEdited.secondPoint.y);
}
if (!CGPointEqualToPoint(self.segmentBeingEdited.thirdPoint, CGPointZero)) {
CGContextAddLineToPoint(context, self.segmentBeingEdited.thirdPoint.x, self.segmentBeingEdited.thirdPoint.y);
}
CGContextStrokePath(context);
// CGContextEndTransparencyLayer(context);
}
incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
erased = TRUE;
return;
}
CGContextSetBlendMode(context, kCGBlendModeNormal);
if (!CGPointEqualToPoint(first, CGPointZero)) {
CGContextMoveToPoint(context, first.x, first.y);
if (!CGPointEqualToPoint(second, CGPointZero)) {
CGContextAddLineToPoint(context, second.x, second.y);
}
if (!CGPointEqualToPoint(third, CGPointZero)) {
CGContextAddLineToPoint(context, third.x, third.y);
}
CGContextStrokePath(context);
}
incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
@end
To recap, i'd like to draw a bunch of angles, then have the ability to edit any of them by tapping the any of the 3 points of the angle I wish to edit. then by dragging, the angle is edited to extend to where the tap is currently located. Just looking to make it better/simpler. Any comments/insight welcome!