0028148: Samples - add 3D Viewer sample for iOS platform
[occt.git] / samples / ios / UIKitSample / UIKitSample / GLViewController.mm
1 // Copyright (c) 2017 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #import <Foundation/Foundation.h>
15
16 #import "GLViewController.h"
17 #import "GLView.h"
18
19 @implementation GLViewController
20
21 // =======================================================================
22 // function : init
23 // purpose  :
24 // =======================================================================
25 - (id) init
26 {
27   self = [super init];
28   
29   if (self) {
30     myOcctViewer = new OcctViewer();
31   }
32   
33   return self;
34 }
35
36 // =======================================================================
37 // function : Draw
38 // purpose  :
39 // =======================================================================
40 - (void) Draw
41 {
42 }
43
44 // =======================================================================
45 // function : Setup
46 // purpose  :
47 // =======================================================================
48 - (void) Setup {
49   if (!myOcctViewer->InitViewer(self.view)) {
50     NSLog(@"Failed to init viewer");
51   }
52   else {
53     [self importScrew:nullptr];
54   }
55 }
56
57 // =======================================================================
58 // function : loadView
59 // purpose  :
60 // =======================================================================
61 - (void) loadView
62 {
63   GLView* aGLView = [[GLView alloc] init];
64   aGLView->myController = self;
65   self.view = aGLView;
66 }
67
68 // =======================================================================
69 // function : touchesBegan
70 // purpose  :
71 // =======================================================================
72 - (void)touchesBegan:(NSSet *)theTouches withEvent:(UIEvent *)theEvent
73 {
74   [super touchesBegan:theTouches withEvent:theEvent];
75   
76   UITouch *aTouch = [theTouches anyObject];
77   if (aTouch != NULL) {
78     CGPoint aTouchPoint = [aTouch locationInView:self.view];
79     myOcctViewer->StartRotation((int)aTouchPoint.x, (int)aTouchPoint.y);
80   }
81 }
82
83 // =======================================================================
84 // function : touchesMoved
85 // purpose  :
86 // =======================================================================
87 - (void)touchesMoved:(NSSet *)theTouches withEvent:(UIEvent *)theEvent
88 {
89   [super touchesMoved:theTouches withEvent:theEvent];
90   
91   UITouch *aTouch = [theTouches anyObject];
92   if (aTouch != NULL) {
93     CGPoint aTouchPoint = [aTouch locationInView:self.view];
94     myOcctViewer->Rotation((int)aTouchPoint.x, (int)aTouchPoint.y);
95   }
96   
97   return;
98 }
99
100 // =======================================================================
101 // function : viewDidLoad
102 // purpose  :
103 // =======================================================================
104 -(void)viewDidLoad
105 {
106   // add zoom recognizer
107   UIPinchGestureRecognizer *aZoomRecognizer = [[UIPinchGestureRecognizer alloc]
108                                                initWithTarget:self
109                                                action:@selector(zoomHandler:)];
110   
111   [[self view] addGestureRecognizer:aZoomRecognizer];
112   
113   // add pan recognizer
114   UIPanGestureRecognizer *aPanRecognizer = [[UIPanGestureRecognizer alloc]
115                                             initWithTarget:self
116                                             action:@selector(panHandler:)];
117   
118   aPanRecognizer.maximumNumberOfTouches = 2;
119   aPanRecognizer.minimumNumberOfTouches = 2;
120   
121   [[self view] addGestureRecognizer:aPanRecognizer];
122   
123   UITapGestureRecognizer *aTapRecognizer = [[UITapGestureRecognizer alloc]
124                                             initWithTarget:self
125                                             action:@selector(tapHandler:)];
126   
127   [[self view] addGestureRecognizer:aTapRecognizer];
128   
129   
130   // add import buttons
131   UIBarButtonItem *importScrewBtn = [[UIBarButtonItem alloc]
132                                      initWithTitle:@"Sample 1"
133                                      style:UIBarButtonItemStylePlain
134                                      target:self
135                                      action:@selector(importScrew:)];
136   
137   UIBarButtonItem *importLinkrodsBtn = [[UIBarButtonItem alloc]
138                                         initWithTitle:@"Sample 2"
139                                         style:UIBarButtonItemStylePlain
140                                         target:self
141                                         action:@selector(importLinkrods:)];
142   
143   UIBarButtonItem *displayAboutDlgBtn = [[UIBarButtonItem alloc]
144                                          initWithTitle:@"About"
145                                          style:UIBarButtonItemStylePlain
146                                          target:self
147                                          action:@selector(displayAboutDlg:)];
148   
149   [self.navigationItem setLeftBarButtonItems:[NSArray arrayWithObjects:importScrewBtn, importLinkrodsBtn, nil]];
150   [self.navigationItem setRightBarButtonItem: displayAboutDlgBtn];
151 }
152
153 // =======================================================================
154 // function : zoomHandler
155 // purpose  :
156 // =======================================================================
157 - (void)zoomHandler:(UIPinchGestureRecognizer *)pinchRecognizer
158 {
159   if ([pinchRecognizer numberOfTouches] > 1)
160   {
161     UIGestureRecognizerState aState = [pinchRecognizer state];
162     if (aState == UIGestureRecognizerStateBegan)
163     {
164       myFirstTouch[0] = [pinchRecognizer locationOfTouch:0 inView:self.view];
165       myFirstTouch[1] = [pinchRecognizer locationOfTouch:1 inView:self.view];
166     }
167     else if (aState == UIGestureRecognizerStateChanged) {
168       CGPoint aLastTouch[2] = {
169         [pinchRecognizer locationOfTouch:0 inView:self.view],
170         [pinchRecognizer locationOfTouch:1 inView:self.view]
171       };
172       
173       double aPinchCenterXStart = ( myFirstTouch[0].x + myFirstTouch[1].x ) / 2.0;
174       double aPinchCenterYStart = ( myFirstTouch[0].y + myFirstTouch[1].y ) / 2.0;
175       
176       double aStartDist = Sqrt( ( myFirstTouch[0].x - myFirstTouch[1].x ) * ( myFirstTouch[0].x - myFirstTouch[1].x ) +
177                               ( myFirstTouch[0].y - myFirstTouch[1].y ) * ( myFirstTouch[0].y - myFirstTouch[1].y ) );
178       double anEndDist = Sqrt( ( aLastTouch[0].x - aLastTouch[1].x ) * ( aLastTouch[0].x - aLastTouch[1].x ) +
179                             ( aLastTouch[0].y - aLastTouch[1].y ) * ( aLastTouch[0].y - aLastTouch[1].y ) );
180       
181       double aDeltaDist = anEndDist - aStartDist;
182       
183       myOcctViewer->Zoom(aPinchCenterXStart, aPinchCenterYStart, aDeltaDist);
184       
185       myFirstTouch[0] = aLastTouch[0];
186       myFirstTouch[1] = aLastTouch[1];
187     }
188   }
189 }
190
191 // =======================================================================
192 // function : panHandler
193 // purpose  :
194 // =======================================================================
195 - (void)panHandler:(UIPanGestureRecognizer *)panRecognizer
196 {
197   if ([panRecognizer numberOfTouches] > 1)
198   {
199     UIGestureRecognizerState aState = [panRecognizer state];
200     if (aState == UIGestureRecognizerStateBegan)
201     {
202       myFirstTouch[0] = [panRecognizer locationOfTouch:0 inView:self.view];
203       myFirstTouch[1] = [panRecognizer locationOfTouch:1 inView:self.view];
204     }
205     else if (aState == UIGestureRecognizerStateChanged) {
206       CGPoint aLastTouch[2] = {
207         [panRecognizer locationOfTouch:0 inView:self.view],
208         [panRecognizer locationOfTouch:1 inView:self.view]
209       };
210       
211       double aPinchCenterXStart = ( myFirstTouch[0].x + myFirstTouch[1].x ) / 2.0;
212       double aPinchCenterYStart = ( myFirstTouch[0].y + myFirstTouch[1].y ) / 2.0;
213       
214       double aPinchCenterXEnd = ( aLastTouch[0].x + aLastTouch[1].x ) / 2.0;
215       double aPinchCenterYEnd = ( aLastTouch[0].y + aLastTouch[1].y ) / 2.0;
216       
217       double aPinchCenterXDev = aPinchCenterXEnd - aPinchCenterXStart;
218       double aPinchCenterYDev = aPinchCenterYEnd - aPinchCenterYStart;
219       
220       myOcctViewer->Pan((int)aPinchCenterXDev, (int)-aPinchCenterYDev);
221     }
222   }
223 }
224
225 // =======================================================================
226 // function : tapHandler
227 // purpose  :
228 // =======================================================================
229 - (void)tapHandler:(UITapGestureRecognizer *)tapRecognizer
230 {
231   CGPoint aTapPoint = [tapRecognizer locationInView:self.view];
232   myOcctViewer->Select(aTapPoint.x, aTapPoint.y);
233 }
234
235 // =======================================================================
236 // function : importScrew
237 // purpose  :
238 // =======================================================================
239 - (void)importScrew:(UIBarButtonItem *)theSender
240 {
241   NSString* aNsPath = [[NSBundle mainBundle] pathForResource:@"screw"
242                                                       ofType:@"step"];
243   std::string aPath = std::string([aNsPath UTF8String]);
244   
245   myOcctViewer->ImportSTEP(aPath);
246   myOcctViewer->FitAll();
247 }
248
249 // =======================================================================
250 // function : importLinkrods
251 // purpose  :
252 // =======================================================================
253 - (void)importLinkrods:(UIBarButtonItem *)theSender
254 {
255   NSString* aNsPath = [[NSBundle mainBundle] pathForResource:@"linkrods"
256                                                       ofType:@"step"];
257   std::string aPath = std::string([aNsPath UTF8String]);
258   
259   myOcctViewer->ImportSTEP(aPath);
260   myOcctViewer->FitAll();
261 }
262
263 // =======================================================================
264 // function : displayAboutDlg
265 // purpose  :
266 // =======================================================================
267 - (void)displayAboutDlg:(UIBarButtonItem *)theSender
268 {
269   UIAlertController* anAbout = [UIAlertController alertControllerWithTitle:@"About"
270                                 message:@"UIKit based application for tutorial to Open CASCADE Technology.\n\n"
271                                       @"Copyright (c) 2017 OPEN CASCADE SAS"
272                                 preferredStyle:UIAlertControllerStyleAlert];
273   
274   UIAlertAction* aDefaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault
275                                                          handler:^(UIAlertAction * action) {}];
276   
277   [anAbout addAction:aDefaultAction];
278   [self presentViewController:anAbout animated:YES completion:nil];
279 }
280
281 @end