I need some help to get started on drawing lines with circle at ends, and measure its length. I am able to draw the line but can't make it moving,having spent hours decided to post on SO.
So please see below image and guide me to get started. Any sample or tutorial using objective c will help.
Thanks :)
The Measure app uses augmented reality (AR) technology to turn your device into a tape measure. You can gauge the size of objects, automatically detect the dimensions of rectangular objects, and save a photo of the measurement.
Hold your phone so the camera is pointing at the object you want to measure and move the phone around until you see a white circle with a dot in the middle. Line the white dot up with a corner on the item you want to measure then press the white button with the + sign in the middle of it.
This idea looked like fun to implement, so I started a new project in Xcode and created a proof-of-concept.
This class is responsible for drawing two circles and a line connecting their centers.
class LineView: UIView {
var startPoint: CGPoint?
var endPoint: CGPoint?
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
private func setup() {
self.backgroundColor = UIColor.clearColor()
self.multipleTouchEnabled = true
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.updatePointsWithTouches(touches)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.updatePointsWithTouches(touches)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.clearPoints()
}
override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
self.clearPoints()
}
private func updatePointsWithTouches(touches: Set<UITouch>) {
if touches.count >= 1 {
self.startPoint = touches[advance(touches.startIndex, 0)].locationInView(self)
}
if touches.count >= 2 {
self.endPoint = touches[advance(touches.startIndex, 1)].locationInView(self)
}
self.setNeedsDisplay()
}
private func clearPoints() {
self.startPoint = nil
self.endPoint = nil
self.setNeedsDisplay()
}
// MARK: - Drawing
override func drawRect(rect: CGRect) {
// draw circle at startPoint
if let sp = self.startPoint {
self.drawTouchCircleAtPoint(sp)
}
// draw circle at endPoint
if let ep = self.endPoint {
self.drawTouchCircleAtPoint(ep)
}
// draw line between points
if let sp = self.startPoint, ep = self.endPoint {
self.drawLineBetweenFirstPoint(sp, secondPoint: ep)
}
}
private func drawTouchCircleAtPoint(p: CGPoint) {
let context = UIGraphicsGetCurrentContext()
CGContextSaveGState(context)
CGContextSetLineWidth(context, 2.0)
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.6)
CGContextAddArc(context, p.x, p.y, CGFloat(30.0), CGFloat(0.0), CGFloat(M_PI * 2), 1)
CGContextFillPath(context)
CGContextRestoreGState(context)
}
private func drawLineBetweenFirstPoint(p1: CGPoint, secondPoint p2: CGPoint) {
let context = UIGraphicsGetCurrentContext()
CGContextSaveGState(context)
CGContextSetStrokeColorWithColor(context, UIColor.whiteColor().colorWithAlphaComponent(0.6).CGColor)
CGContextSetLineWidth(context, 1.0)
CGContextMoveToPoint(context, p1.x, p1.y)
CGContextAddLineToPoint(context, p2.x, p2.y)
CGContextStrokePath(context)
CGContextRestoreGState(context)
}
}
This class introduces two private properties: startPoint
and endPoint
, which keep track of where the user's fingers are touching the view.
In this class you'll find a setup()
function that is called from all the initializers. self.multipleTouchEnabled = true
is crucial here so the view can detect multiple touches at the same time.
The touchesBegan/Moved/Ended/Cancelled
functions call helper functions that extract the locations of the UITouch
instances in the touches
set.
Finally, the last three functions are responsible for drawing the circles and the connecting line.
class InteractiveImageView: UIImageView {
private var lineView: LineView!
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
self.setup()
}
private func setup() {
self.userInteractionEnabled = true
self.lineView = LineView(frame: self.bounds)
self.addSubview(self.lineView)
}
}
This UIImageView
subclass has an embedded LineView
to capture the multi-touch events.
You can use these classes with a Storyboard too! Just drag out a UIImageView
, change it's class to InteractiveImageView
, set the proper constraints, and run the app. I'll leave it up to you to draw the text on the axis between the center of the circles.
Here's a picture of my proof-of-concept.
For those looking for an Objective-C solution, please see below for the implementation files of LineView
and InteractiveImageView
.
#import "LineView.h"
@interface LineView ()
@property (nonatomic) CGPoint startPoint;
@property (nonatomic) CGPoint endPoint;
@end
@implementation LineView
- (instancetype)init
{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup
{
self.backgroundColor = [UIColor clearColor];
self.multipleTouchEnabled = true;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self updatePointsWithTouches:touches];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self updatePointsWithTouches:touches];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self clearPoints];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self clearPoints];
}
- (void)clearPoints
{
self.startPoint = CGPointZero;
self.endPoint = CGPointZero;
[self setNeedsDisplay];
}
- (void)updatePointsWithTouches:(NSSet *)touches
{
if (touches.count >= 1) {
UITouch *touch = [touches allObjects][0];
self.startPoint = [touch locationInView:self];
}
if (touches.count >= 2) {
UITouch *touch = [touches allObjects][1];
self.endPoint = [touch locationInView:self];
}
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
if (self.startPoint.x != 0 && self.startPoint.y != 0) {
[self drawTouchCircleAtPoint:self.startPoint];
}
if (self.endPoint.x != 0 && self.endPoint.y != 0) {
[self drawTouchCircleAtPoint:self.endPoint];
}
if (self.endPoint.x != 0 && self.endPoint.y != 0 &&
self.startPoint.x != 0 && self.startPoint.y != 0) {
[self drawLineBetweenFirstPoint:self.startPoint end:self.endPoint];
}
}
- (void)drawLineBetweenFirstPoint:(CGPoint)startPoint end:(CGPoint)endPoint
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetStrokeColorWithColor(context, [[[UIColor whiteColor] colorWithAlphaComponent:0.6] CGColor]);
CGContextSetLineWidth(context, 1.0);
CGContextMoveToPoint(context, startPoint.x, startPoint.y);
CGContextAddLineToPoint(context, endPoint.x, endPoint.y);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
- (void)drawTouchCircleAtPoint:(CGPoint)CirclePoint
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetLineWidth(context, 2.0);
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 0.6);
CGContextAddArc(context, CirclePoint.x, CirclePoint.y, 30.0, 30.0, M_PI * 2, YES);
CGContextFillPath(context);
CGContextRestoreGState(context);
}
@end
#import "InteractiveImageView.h"
#import "LineView.h"
@interface InteractiveImageView ()
@property (strong, nonatomic) LineView *lineView;
@end
@implementation InteractiveImageView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self setup];
}
return self;
}
- (void)setup
{
self.userInteractionEnabled = YES;
self.lineView = [[LineView alloc] initWithFrame:self.bounds];
[self addSubview:self.lineView];
}
@end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With