-
Notifications
You must be signed in to change notification settings - Fork 0
/
OpenIGTLinkConnect.cs
217 lines (175 loc) · 8.62 KB
/
OpenIGTLinkConnect.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// This code is based on the one provided in: https://github.com/franklinwk/OpenIGTLink-Unity
// Modified by Alicia Pose Díez de la Lastra, from Universidad Carlos III de Madrid
using UnityEngine;
using System;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Collections;
using System.Threading;
using System.Collections.Generic;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Runtime;
public class OpenIGTLinkConnect : MonoBehaviour
{
///////// CONNECT TO 3D SLICER PARAMETERS /////////
uint headerSize = 58; // Size of the header of every OpenIGTLink message
private SocketHandler socket; // Socket to connect to Slicer
bool isConnected; // Boolean to check if the socket is connected
public string ipString="localhost"; // IP address of the computer running Slicer
public int port = 18944; // Port of the computer running Slicer
///////// GENERAL VARIABLES /////////
int scaleMultiplier = 1; // Help variable to transform meters to millimeters and vice versa
///////// SEND /////////
public List<ModelInfo> infoToSend; // Array of Models to send to Slicer
/// CRC ECMA-182 to send messages to Slicer ///
CRC64 crcGenerator;
string CRC;
ulong crcPolynomial;
string crcPolynomialBinary = "0100001011110000111000011110101110101001111010100011011010010011";
//public GameObject movingElement;
void Start()
{
// Initialize CRC Generator
crcGenerator = new CRC64();
crcPolynomial = Convert.ToUInt64(crcPolynomialBinary, 2);
crcGenerator.Init(crcPolynomial);
isConnected = ConnectToSlicer(ipString, port);
//IEnumerable send = SendTransformInfo();
StartCoroutine("SendTransformInfo");
}
// This function is called when the user activates the connectivity switch to start the communication with 3D Slicer
public bool OnConnectToSlicerClick(string ipString, int port)
{
isConnected = ConnectToSlicer(ipString, port);
return isConnected;
}
// Create a new socket handler and connect it to the server with the ip address and port provided in the function
bool ConnectToSlicer(string ipString, int port)
{
socket = new SocketHandler();
Debug.Log("ipString: " + ipString);
Debug.Log("port: " + port);
bool isConnected = socket.Connect(ipString, port);
Debug.Log("Connected: " + isConnected);
return isConnected;
}
// Routine that continuously sends the transform information of every model in infoToSend to 3D Slicer
public IEnumerator SendTransformInfo()
{
while (true)
{
Debug.Log("Sending...");
yield return null; // If you had written yield return new WaitForSeconds(1); it would have waited 1 second before executing the code below.
// Loop foreach element in infoToSend
foreach (ModelInfo element in infoToSend)
{
SendMessageToServer.SendTransformMessage(element, scaleMultiplier, crcGenerator, CRC, socket);
}
}
}
// Routine that continuously listents to the incoming information from 3D Slicer. In the present code, this information could be in the form of a transform or an image message
/*public IEnumerator ListenSlicerInfo()
{
while (true)
{
Debug.Log("Listening...");
yield return null;
////////// READ THE HEADER OF THE INCOMING MESSAGES //////////
byte[] iMSGbyteArray = socket.Listen(headerSize);
if (iMSGbyteArray.Length >= (int)headerSize)
{
////////// READ THE HEADER OF THE INCOMING MESSAGES //////////
// Store the information of the header in the structure iHeaderInfo
ReadMessageFromServer.HeaderInfo iHeaderInfo = ReadMessageFromServer.ReadHeaderInfo(iMSGbyteArray);
////////// READ THE BODY OF THE INCOMING MESSAGES //////////
// Get the size of the body from the header information
uint bodySize = Convert.ToUInt32(iHeaderInfo.bodySize);
// Process the message when it is complete (that means, we have received as many bytes as the body size + the header size)
if (iMSGbyteArray.Length >= (int)bodySize + (int)headerSize)
{
// Compare different message types and act accordingly
if ((iHeaderInfo.msgType).Contains("TRANSFORM"))
{
// Extract the transform matrix from the message
Matrix4x4 matrix = ReadMessageFromServer.ExtractTransformInfo(iMSGbyteArray, movingElement, scaleMultiplier, (int)iHeaderInfo.headerSize);
// Apply the transform matrix to the object
ApplyTransformToGameObject(matrix, movingElement);
}
else if ((iHeaderInfo.msgType).Contains("IMAGE"))
{
// Read and apply the image content to our preview plane
//ApplyImageInfo(iMSGbyteArray, iHeaderInfo);
}
}
}
}
}*/
/// Apply transform information to GameObject ///
/*void ApplyTransformToGameObject(Matrix4x4 matrix, GameObject gameObject)
{
Vector3 translation = matrix.GetColumn(3);
//gameObject.transform.localPosition = new Vector3(-translation.x, translation.y, translation.z);
//Vector3 rotation= matrix.rotation.eulerAngles;
//gameObject.transform.localRotation = Quaternion.Euler(rotation.x, -rotation.y, -rotation.z);
if (translation.x > 10000 || translation.y > 10000 || translation.z > 10000)
{
gameObject.transform.position = new Vector3(0, 0, 0.5f);
Debug.Log("Out of limits. Default position assigned.");
}
else
{
gameObject.transform.localPosition = new Vector3(-translation.x, translation.y, translation.z);
Vector3 rotation = matrix.rotation.eulerAngles;
gameObject.transform.localRotation = Quaternion.Euler(rotation.x, -rotation.y, -rotation.z);
}
}*/
//////////////////////////////// INCOMING IMAGE MESSAGE ////////////////////////////////
/*void ApplyImageInfo(byte[] iMSGbyteArray, ReadMessageFromServer.HeaderInfo iHeaderInfo)
{
// Store the information of the image's body in the structure iImageInfo
ReadMessageFromServer.ImageInfo iImageInfo = ReadMessageFromServer.ReadImageInfo(iMSGbyteArray, headerSize, iHeaderInfo.extHeaderSize);
if (iImageInfo.numPixX > 0 && iImageInfo.numPixY > 0)
{
// Define the material and the texture of the plane that will display the image
mediaMaterial = movingPlane.GetComponent<MeshRenderer>().material;
mediaTexture = new Texture2D(iImageInfo.numPixX, iImageInfo.numPixY, TextureFormat.Alpha8, false);
fixPlaneMaterial = fixPlane.GetComponent<MeshRenderer>().material;
// Define the array that will store the image's pixels
byte[] bodyArray_iImData = new byte[iImageInfo.numPixX * iImageInfo.numPixY];
byte[] bodyArray_iImDataInv = new byte[bodyArray_iImData.Length];
Buffer.BlockCopy(iMSGbyteArray, iImageInfo.offsetBeforeImageContent, bodyArray_iImData, 0, bodyArray_iImData.Length);
// Invert the values of the pixels to have a dark background
for (int i = 0; i < bodyArray_iImData.Length; i++)
{
bodyArray_iImDataInv[i] = (byte)(255 - bodyArray_iImData[i]);
}
// Load the pixels into the texture and the material
mediaTexture.LoadRawTextureData(bodyArray_iImDataInv);
mediaTexture.Apply();
mediaMaterial.mainTexture = mediaTexture;
fixPlaneMaterial.mainTexture = mediaTexture;
}
else
{
//Create black texture
}
}*/
// Called when the user disconnects Unity from 3D Slicer using the connectivity switch
public void OnDisconnectClick()
{
socket.Disconnect();
Debug.Log("Disconnected from the server");
}
// Execute this function when the user exits the application
void OnApplicationQuit()
{
// Release the socket.
if (socket != null)
{
socket.Disconnect();
}
}
}