0028148: Samples - add 3D Viewer sample for iOS platform
[occt.git] / samples / ios / UIKitSample / UIKitSample / OcctViewer.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 #include "OcctViewer.h"
15 #include "OcctDocument.h"
16
17 #include <AIS_ConnectedInteractive.hxx>
18 #include <AIS_Shape.hxx>
19 #include <Aspect_DisplayConnection.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRepMesh_IncrementalMesh.hxx>
22 #include <BRepTools.hxx>
23 #include <Cocoa_Window.hxx>
24 #include <Message.hxx>
25 #include <Message_Messenger.hxx>
26 #include <OpenGl_GraphicDriver.hxx>
27 #include <Prs3d.hxx>
28 #include <Prs3d_Drawer.hxx>
29 #include <STEPControl_Reader.hxx>
30 #include <STEPCAFControl_Reader.hxx>
31 #include <TDF_Tool.hxx>
32 #include <TDF_ChildIterator.hxx>
33 #include <Transfer_TransientProcess.hxx>
34 #include <XSControl_TransferReader.hxx>
35 #include <XCAFDoc_DocumentTool.hxx>
36
37 // =======================================================================
38 // function : OcctViewer
39 // purpose  :
40 // =======================================================================
41 OcctViewer::OcctViewer()
42 {
43   myDoc = new OcctDocument();
44 }
45
46 // =======================================================================
47 // function : ~OcctViewer
48 // purpose  :
49 // =======================================================================
50 OcctViewer::~OcctViewer()
51 {
52   //
53 }
54
55 // =======================================================================
56 // function : release
57 // purpose  :
58 // =======================================================================
59 void OcctViewer::release()
60 {
61   myContext.Nullify();
62   if (!myView.IsNull())
63   {
64     myView->Remove();
65   }
66   myView.Nullify();
67   myViewer.Nullify();
68   
69   myDoc.Nullify();
70 }
71
72 // =======================================================================
73 // function : InitViewer
74 // purpose  :
75 // =======================================================================
76 bool OcctViewer::InitViewer (UIView* theWin)
77 {
78   EAGLContext* aRendCtx = [EAGLContext currentContext];
79   if (theWin == NULL || aRendCtx   == NULL)
80   {
81     NSLog(@"Error: No active EAGL context!");
82     release();
83     return false;
84   }
85   
86   if (!myView.IsNull())
87   {
88     myView->MustBeResized();
89     myView->Invalidate();
90   }
91   else
92   {
93     Handle(Aspect_DisplayConnection) aDisplayConnection = new Aspect_DisplayConnection();
94     Handle(Graphic3d_GraphicDriver) aGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection);
95     
96     // Create Viewer
97     myViewer = new V3d_Viewer(aGraphicDriver);
98     myViewer->SetDefaultLights();
99     myViewer->SetLightOn();
100     
101     // Create AIS context
102     myContext = new AIS_InteractiveContext(myViewer);
103     myContext->SetDisplayMode((int)AIS_DisplayMode::AIS_Shaded, false);
104     
105     myView = myViewer->CreateView();
106     myView->TriedronDisplay (Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.20, V3d_ZBUFFER);
107     
108     Handle(Cocoa_Window) aCocoaWindow = new Cocoa_Window(theWin);
109     myView->SetWindow(aCocoaWindow, aRendCtx);
110     if (!aCocoaWindow->IsMapped())
111     {
112       aCocoaWindow->Map();
113     }
114     
115     myView->Redraw();
116     myView->MustBeResized();
117   }
118   
119   return true;
120 }
121
122 // =======================================================================
123 // function : FitAll
124 // purpose  :
125 // =======================================================================
126 void OcctViewer::FitAll()
127 {
128   if (!myView.IsNull())
129   {
130     myView->FitAll();
131     myView->ZFitAll();
132   }
133 }
134
135 // =======================================================================
136 // function : StartRotation
137 // purpose  :
138 // =======================================================================
139 void OcctViewer::StartRotation(int theX, int theY)
140 {
141   if (!myView.IsNull())
142   {
143     myView->StartRotation(theX, theY);
144   }
145 }
146
147 // =======================================================================
148 // function : Rotation
149 // purpose  :
150 // =======================================================================
151 void OcctViewer::Rotation(int theX, int theY)
152 {
153   if (!myView.IsNull())
154   {
155     myView->Rotation(theX, theY);
156   }
157 }
158
159 // =======================================================================
160 // function : Pan
161 // purpose  :
162 // =======================================================================
163 void OcctViewer::Pan(int theX, int theY)
164 {
165   if (!myView.IsNull())
166   {
167     myView->Pan(theX, theY, 1, Standard_False);
168   }
169 }
170
171 // =======================================================================
172 // function : Zoom
173 // purpose  :
174 // =======================================================================
175 void OcctViewer::Zoom(int theX, int theY, double theDelta)
176 {
177   if (!myView.IsNull())
178   {
179     if (theX >=0 && theY >=0)
180     {
181       myView->StartZoomAtPoint(theX, theY);
182       myView->ZoomAtPoint(0, 0, (int) theDelta, (int) theDelta);
183     }
184     else
185     {
186       double aCoeff = Abs(theDelta) / 100.0 + 1.0;
187       aCoeff = theDelta > 0.0 ? aCoeff : 1.0 / aCoeff;
188       myView->SetZoom(aCoeff, Standard_True);
189     }
190   }
191 }
192
193 // =======================================================================
194 // function : Select
195 // purpose  :
196 // =======================================================================
197 void OcctViewer::Select(int theX, int theY)
198 {
199   if (!myContext.IsNull())
200   {
201     myContext->ClearSelected(Standard_False);
202     myContext->MoveTo(theX, theY, myView, Standard_False);
203     myContext->Select(Standard_False);
204   }
205 }
206
207 // =======================================================================
208 // function : ImportSTEP
209 // purpose  :
210 // =======================================================================
211 bool OcctViewer::ImportSTEP(std::string theFilename)
212 {
213   // create a new document
214   myDoc->InitDoc();
215   
216   STEPCAFControl_Reader aReader;
217   Handle(XSControl_WorkSession) aSession = aReader.Reader().WS();
218   
219   try {
220     if (!aReader.ReadFile (theFilename.c_str()))
221     {
222       clearSession (aSession);
223       return false;
224     }
225     
226     if (!aReader.Transfer (myDoc->ChangeDocument()))
227     {
228       clearSession (aSession);
229       return false;
230     }
231     
232     clearSession(aSession);
233   } catch (Standard_Failure theFailure) {
234     Message::DefaultMessenger()->Send (TCollection_AsciiString ("Exception raised during STEP import\n[")
235                                        + theFailure.GetMessageString() + "]\n" + theFilename.c_str(), Message_Fail);
236     return false;
237   }
238   
239   Handle(XCAFDoc_ShapeTool) aShapeTool = XCAFDoc_DocumentTool::ShapeTool (myDoc->Document()->Main());
240   Handle(XCAFDoc_ColorTool) aColorTool = XCAFDoc_DocumentTool::ColorTool (myDoc->Document()->Main());
241   
242   TDF_LabelSequence aLabels;
243   aShapeTool->GetFreeShapes (aLabels);
244   
245   // perform meshing explicitly
246   TopoDS_Compound aCompound;
247   BRep_Builder    aBuildTool;
248   aBuildTool.MakeCompound (aCompound);
249   for (Standard_Integer aLabIter = 1; aLabIter <= aLabels.Length(); ++aLabIter)
250   {
251     TopoDS_Shape     aShape;
252     const TDF_Label& aLabel = aLabels.Value (aLabIter);
253     if (XCAFDoc_ShapeTool::GetShape (aLabel, aShape))
254     {
255       aBuildTool.Add (aCompound, aShape);
256     }
257   }
258   
259   Handle(Prs3d_Drawer) aDrawer = myContext->DefaultDrawer();
260   Standard_Real aDeflection = Prs3d::GetDeflection (aCompound, aDrawer);
261   if (!BRepTools::Triangulation (aCompound, aDeflection))
262   {
263     BRepMesh_IncrementalMesh anAlgo;
264     anAlgo.ChangeParameters().Deflection = aDeflection;
265     anAlgo.ChangeParameters().Angle = aDrawer->HLRAngle();
266     anAlgo.ChangeParameters().InParallel = Standard_True;
267     anAlgo.SetShape     (aCompound);
268     anAlgo.Perform();
269   }
270   
271   // clear presentations
272   clearContext();
273   
274   // create presentations
275   MapOfPrsForShapes aMapOfShapes;
276   XCAFPrs_Style aDefStyle;
277   aDefStyle.SetColorSurf (Quantity_NOC_GRAY65);
278   aDefStyle.SetColorCurv (Quantity_NOC_GRAY65);
279   for (Standard_Integer aLabIter = 1; aLabIter <= aLabels.Length(); ++aLabIter)
280   {
281     const TDF_Label& aLabel = aLabels.Value (aLabIter);
282     displayWithChildren (*aShapeTool, *aColorTool, aLabel, TopLoc_Location(), aDefStyle, "", aMapOfShapes);
283   }
284   
285   return true;
286 }
287
288 // =======================================================================
289 // function : displayWithChildren
290 // purpose  :
291 // =======================================================================
292 void OcctViewer::displayWithChildren (XCAFDoc_ShapeTool&             theShapeTool,
293                                       XCAFDoc_ColorTool&             theColorTool,
294                                       const TDF_Label&               theLabel,
295                                       const TopLoc_Location&         theParentTrsf,
296                                       const XCAFPrs_Style&           theParentStyle,
297                                       const TCollection_AsciiString& theParentId,
298                                       MapOfPrsForShapes&             theMapOfShapes)
299 {
300   TDF_Label aRefLabel = theLabel;
301   if (theShapeTool.IsReference (theLabel))
302   {
303     theShapeTool.GetReferredShape (theLabel, aRefLabel);
304   }
305   
306   TCollection_AsciiString anEntry;
307   TDF_Tool::Entry (theLabel, anEntry);
308   if (!theParentId.IsEmpty())
309   {
310     anEntry = theParentId + "\n" + anEntry;
311   }
312   anEntry += ".";
313   
314   if (!theShapeTool.IsAssembly (aRefLabel))
315   {
316     Handle(AIS_InteractiveObject) anAis;
317     if (!theMapOfShapes.Find (aRefLabel, anAis))
318     {
319       anAis = new CafShapePrs (aRefLabel, theParentStyle, Graphic3d_NOM_SHINY_PLASTIC);
320       theMapOfShapes.Bind (aRefLabel, anAis);
321     }
322     
323     Handle(TCollection_HAsciiString) anId      = new TCollection_HAsciiString (anEntry);
324     Handle(AIS_ConnectedInteractive) aConnected = new AIS_ConnectedInteractive();
325     aConnected->Connect (anAis, theParentTrsf.Transformation());
326     aConnected->SetOwner (anId);
327     aConnected->SetLocalTransformation (theParentTrsf.Transformation());
328     aConnected->SetHilightMode(1);
329     myContext->Display  (aConnected, Standard_False);
330     return;
331   }
332   
333   XCAFPrs_Style aDefStyle = theParentStyle;
334   Quantity_Color aColor;
335   if (theColorTool.GetColor (aRefLabel, XCAFDoc_ColorGen, aColor))
336   {
337     aDefStyle.SetColorCurv (aColor);
338     aDefStyle.SetColorSurf (aColor);
339   }
340   if (theColorTool.GetColor (aRefLabel, XCAFDoc_ColorSurf, aColor))
341   {
342     aDefStyle.SetColorSurf (aColor);
343   }
344   if (theColorTool.GetColor (aRefLabel, XCAFDoc_ColorCurv, aColor))
345   {
346     aDefStyle.SetColorCurv (aColor);
347   }
348   
349   for (TDF_ChildIterator childIter (aRefLabel); childIter.More(); childIter.Next())
350   {
351     TDF_Label aLabel = childIter.Value();
352     if (!aLabel.IsNull()
353         && (aLabel.HasAttribute() || aLabel.HasChild()))
354     {
355       TopLoc_Location aTrsf = theParentTrsf * theShapeTool.GetLocation (aLabel);
356       displayWithChildren (theShapeTool, theColorTool, aLabel, aTrsf, aDefStyle, anEntry, theMapOfShapes);
357     }
358   }
359 }
360
361 // =======================================================================
362 // function : clearSession
363 // purpose  :
364 // =======================================================================
365 void OcctViewer::clearSession (const Handle(XSControl_WorkSession)& theSession)
366 {
367   if (theSession.IsNull())
368   {
369     return;
370   }
371   
372   Handle(Transfer_TransientProcess) aMapReader = theSession->TransferReader()->TransientProcess();
373   if (!aMapReader.IsNull())
374   {
375     aMapReader->Clear();
376   }
377   
378   Handle(XSControl_TransferReader) aTransferReader = theSession->TransferReader();
379   if (!aTransferReader.IsNull())
380   {
381     aTransferReader->Clear(1);
382   }
383 }
384
385 // =======================================================================
386 // function : clearContext
387 // purpose  :
388 // =======================================================================
389 void OcctViewer::clearContext ()
390 {
391   if (!myContext.IsNull())
392   {
393     myContext->ClearSelected(Standard_False);
394     myContext->RemoveAll(Standard_False);
395   }
396 }