Package omero :: Package util :: Module ROI_utils
[hide private]
[frames] | no frames]

Source Code for Module omero.util.ROI_utils

  1  # 
  2  # 
  3  #------------------------------------------------------------------------------ 
  4  #  Copyright (C) 2006-2009 University of Dundee. All rights reserved. 
  5  # 
  6  # 
  7  #       This program is free software; you can redistribute it and/or modify 
  8  #  it under the terms of the GNU General Public License as published by 
  9  #  the Free Software Foundation; either version 2 of the License, or 
 10  #  (at your option) any later version. 
 11  #  This program is distributed in the hope that it will be useful, 
 12  #  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  #  GNU General Public License for more details. 
 15  # 
 16  #  You should have received a copy of the GNU General Public License along 
 17  #  with this program; if not, write to the Free Software Foundation, Inc., 
 18  #  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 19  # 
 20  #------------------------------------------------------------------------------ 
 21   
 22  ### 
 23  # 
 24  # ROIUtils allows the mapping of omero.model.ROIDataTypesI to python types 
 25  # and to create ROIDataTypesI from ROIUtil types.  
 26  # These methods also implement the acceptVisitor method linking to the ROIDrawingCanvas. 
 27  # 
 28  # 
 29  # @author  Jean-Marie Burel      
 30  #       <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a> 
 31  # @author       Donald MacDonald &nbsp;&nbsp;&nbsp;&nbsp; 
 32  #       <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a> 
 33  # @version 3.0 
 34  # <small> 
 35  # (<b>Internal version:</b> $Revision: $Date: $) 
 36  # </small> 
 37  # @since 3.0-Beta4 
 38  #/ 
 39   
 40  from omero.model import RoiI 
 41  from omero.model import EllipseI 
 42  from omero.model import LineI 
 43  from omero.model import RectI 
 44  from omero.model import PointI 
 45  from omero.model import TextI 
 46  from omero.model import PolylineI 
 47  from omero.model import PolygonI 
 48  from omero.model import PathI 
 49  from omero.rtypes import rdouble  
 50  from omero.rtypes import rstring  
 51  from omero.rtypes import rint  
 52  from omero.rtypes import rfloat  
 53   
 54   
 55  ## 
 56  # abstract, defines the method that call it as abstract. 
 57  # 
 58  # 
59 -def abstract():
60 import inspect 61 caller = inspect.getouterframes(inspect.currentframe())[1][3] 62 raise NotImplementedError(caller + ' must be implemented in subclass')
63 64 ## 65 # ShapeSettingsData contains all the display information about the ROI that aggregates it. 66 #
67 -class ShapeSettingsData:
68 69 ## 70 # Initialises the default values of the ShapeSettings. 71 # Stroke has default colour of darkGrey 72 # StrokeWidth defaults to 1 73 #
74 - def __init__(self):
75 self.strokeColour = rstring('#444444'); 76 self.strokeWidth = rint(1); 77 self.strokeOpacity = rfloat(0); 78 self.strokeDashArray = rstring(''); 79 self.strokeDashOffset = rint(0); 80 self.strokeLineCap = rstring(''); 81 self.strokeLineJoin = rstring(''); 82 self.strokeMiterLimit = rint(0); 83 self.fillColour = rstring('#222222'); 84 self.fillOpacity = rfloat(0); 85 self.fillRule = rstring('');
86 87 ## 88 # Applies the settings in the ShapeSettingsData to the ROITypeI 89 # @param shape the omero.model.ROITypeI that these settings will be applied to 90 #
91 - def setROIShapeSettings(self, shape):
92 shape.setStrokeColor(self.strokeColour); 93 shape.setStrokeWidth(self.strokeWidth); 94 shape.setStrokeDashArray(self.strokeDashArray); 95 shape.setStrokeDashOffset(self.strokeDashOffset); 96 shape.setStrokeLineCap(self.strokeLineCap); 97 shape.setStrokeLineJoin(self.strokeLineJoin); 98 shape.setStrokeMiterLimit(self.strokeMiterLimit); 99 shape.setFillColor(self.fillColour); 100 shape.setFillOpacity(self.fillOpacity); 101 shape.setFillRule(self.fillRule);
102 103 ## 104 # Set the Stroke settings of the ShapeSettings. 105 # @param colour The colour of the stroke. 106 # @param width The stroke width. 107 # @param opacity The stroke opacity. 108 #
109 - def setStrokeSettings(self, colour, width = 1, opacity = 0):
110 self.strokeColour = rsting(colour); 111 self.strokeWidth = rint(width); 112 self.strokeOpacity = rfloat(opacity);
113 114 ### 115 # Set the Fill Settings for the ShapeSettings. 116 # @param colour The fill colour of the shape. 117 # @param opacity The opacity of the fill.
118 - def setFillSettings(self, colour, opacity = 0):
119 self.fillColour = rsting(colour); 120 self.fillOpacity = rfloat(opacity);
121 122 ## 123 # Get the stroke settings as the tuple (strokeColour, strokeWidth). 124 # @return See above. 125 #
126 - def getStrokeSettings(self):
127 return (self.strokeColour.getValue(), self.strokeWidth.getValue());
128 129 ## 130 # Get the fill setting as a tuple of (fillColour, opacity) 131 # @return See above. 132 #
133 - def getFillSettings(self):
134 return (self.fillColour.getValue(), self.fillOpacity.getValue());
135 136 ## 137 # Get the tuple ((stokeColor, strokeWidth), (fillColour, fillOpacity)). 138 # @return see above. 139 #
140 - def getSettings(self):
141 return (self.getStrokeSettings(), self.getFillSettings());
142 143 ## 144 # Set the current shapeSettings from the ROI roi. 145 # @param roi see above. 146 #
147 - def getShapeSettingsFromROI(self, roi):
148 self.strokeColour = roi.getStrokeColor(); 149 self.strokeWidth = roi.getStrokeWidth(); 150 self.strokeOpacity = roi.getStrokeOpacity(); 151 self.strokeDashArray = roi.getStrokeDashArray(); 152 self.strokeDashOffset = roi.getStrokeDashOffset(); 153 self.strokeLineCap = roi.getStrokeLineCap(); 154 self.strokeLineJoin = roi.getStrokeLineJoin(); 155 self.strokeMiterLimit = roi.getStrokeMiterLimit(); 156 self.fillColour = roi.getFillColor(); 157 self.fillOpacity = roi.getFillOpacity(); 158 self.fillRule = roi.getFillRule();
159 160 ## 161 # This class stores the ROI Coordinate (Z,T). 162 #
163 -class ROICoordinate:
164 165 ## 166 # Initialise the ROICoordinate. 167 # @param z The z-section. 168 # @param t The timepoint.
169 - def __init__(self, z = 0, t = 0):
170 self.theZ = rint(z); 171 self.theT = rint(t);
172 173 ## 174 # Set the (z, t) for the roi using the (z, t) of the ROICoordinate. 175 # @param roi The ROI to set the (z, t) on. 176 #
177 - def setROICoord(self, roi):
178 roi.setTheZ(self.theZ); 179 roi.setTheT(self.theT);
180 181 ## 182 # Get the (z, t) from the ROI. 183 # @param See above. 184 #
185 - def setCoordFromROI(self, roi):
186 self.theZ = roi.getTheZ(); 187 self.theT = roi.getTheT();
188 189 ## 190 # Interface to inherit for accepting ROIDrawing as a visitor. 191 # @param visitor The ROIDrawingCompoent. 192 #
193 -class ROIDrawingI:
194 - def acceptVisitor(self, visitor):
195 abstract();
196 197 ## 198 # The base class for all ROIShapeData objects. 199 #
200 -class ShapeData:
201 202 ## 203 # Constructor sets up the coord, shapeSettings and ROI objects. 204 #
205 - def __init__(self):
206 self.coord = ROICoordinate(); 207 self.shapeSettings = ShapeSettingsData(); 208 self.ROI = None;
209 210 ## 211 # Set the coord of the class to coord. 212 # @param See above. 213 #
214 - def setCoord(self, coord):
215 self.coord = coord;
216 217 ## 218 # Set the ROICoordinate of the roi. 219 # @param roi See above. 220 #
221 - def setROICoord(self, roi):
222 self.coord.setROICoord(roi);
223 224 ## 225 # Set the Geometry of the roi from the geometry in ShapeData. 226 # @param roi See above. 227 #
228 - def setROIGeometry(self, roi):
229 abstract();
230 231 ## 232 # Set the Settings of the ShapeDate form the settings object. 233 # @param settings See above. 234 #
235 - def setShapeSettings(self, settings):
236 self.shapeSettings = settings;
237 238 ## 239 # Set the Settings of the roi from the setting in ShapeData. 240 # @param roi See above. 241 #
242 - def setROIShapeSettings(self, roi):
243 self.shapeSettings.setROIShapeSettings(roi);
244 245 ## 246 # Accept visitor. 247 # @param visitor See above. 248 #
249 - def acceptVisitor(self, visitor):
250 abstract();
251 252 ## 253 # Create the base type of ROI for this shape. 254 #
255 - def createBaseType(self):
256 abstract();
257 258 ## 259 # Get the roi from the ShapeData. If the roi already exists return it. 260 # Otherwise create it from the ShapeData and return it. 261 # @return See above. 262 #
263 - def getROI(self):
264 if(self.roi != None): 265 return self.roi; 266 self.roi = self.createBaseType(); 267 self.setROICoord(roi); 268 self.setROIGeometry(roi); 269 self.setROIShapeSettings(roi); 270 return self.roi;
271 272 ## 273 # Set the shape settings object from the roi. 274 # @param roi see above. 275 #
276 - def getShapeSettingsFromROI(self, roi):
277 self.shapeSettings.getShapeSettingsFromROI(roi);
278 279 ## 280 # Set the ROICoordinate from the roi. 281 # @param roi See above. 282 #
283 - def getCoordFromROI(self, roi):
284 self.coord.setCoordFromROI(roi);
285 286 ## 287 # Set the Geometr from the roi. 288 # @param roi See above. 289 #
290 - def getGeometryFromROI(self , roi):
291 abstract();
292 293 ## 294 # Get all settings from the roi, Geomerty, Shapesettins, ROICoordinate. 295 # @param roi See above. 296 #
297 - def fromROI(self, roi):
298 self.roi = roi; 299 self.getShapeSettingsFromROI(roi); 300 self.getCoordFromROI(roi); 301 self.getGeometryFromROI(roi);
302 303 ## 304 # The EllispeData class contains all the manipulation and create of EllipseI 305 # types. 306 # It also accepts the ROIDrawingUtils visitor for drawing ellipses. 307 #
308 -class EllipseData(ShapeData, ROIDrawingI):
309 310 ## 311 # Constructor for EllipseData object. 312 # @param roicoord The ROICoordinate of the object (default: 0,0) 313 # @param cx The centre x coordinate of the ellipse. 314 # @param cy The centre y coordinate of the ellipse. 315 # @param rx The major axis of the ellipse. 316 # @param ry The minor axis of the ellipse.
317 - def __init__(self, roicoord = ROICoordinate(), cx = 0, cy = 0, rx = 0, ry = 0):
318 ShapeData.__init__(self); 319 self.cx = rdouble(cx); 320 self.cy = rdouble(cy); 321 self.rx = rdouble(rx); 322 self.ry = rdouble(ry); 323 self.setCoord(roicoord);
324 325 ## 326 # overridden, @See ShapeData#setROIGeometry 327 #
328 - def setROIGeometry(self, ellipse):
329 ellipse.setTheZ(self.coord.theZ); 330 ellipse.setTheT(self.coord.theZ); 331 ellipse.setCx(self.cx); 332 ellipse.setCy(self.cy); 333 ellipse.setRx(self.rx); 334 ellipse.setRy(self.ry);
335 336 ## 337 # overridden, @See ShapeData#getGeometryFromROI 338 #
339 - def getGeometryFromROI(self, roi):
340 self.cx = roi.getCx(); 341 self.cy = roi.getCy(); 342 self.rx = roi.getRx(); 343 self.ry = roi.getRy();
344 345 ## 346 # overridden, @See ShapeData#createBaseType 347 #
348 - def createBaseType(self):
349 return EllipseI();
350 351 ## 352 # overridden, @See ShapeData#acceptVisitor 353 #
354 - def acceptVisitor(self, visitor):
355 visitor.drawEllipse(self.cx.getValue(), self.cy.getValue(), self.rx.getValue(), self.ry.getValue(), self.shapeSettings.getSettings());
356 357 ## 358 # The RectangleData class contains all the manipulation and create of RectI 359 # types. 360 # It also accepts the ROIDrawingUtils visitor for drawing rectangles. 361 #
362 -class RectangleData(ShapeData, ROIDrawingI):
363 364 ## 365 # Constructor for RectangleData object. 366 # @param roicoord The ROICoordinate of the object (default: 0,0) 367 # @param x The top left x - coordinate of the shape. 368 # @param y The top left y - coordinate of the shape. 369 # @param width The width of the shape. 370 # @param height The height of the shape.
371 - def __init__(self, roicoord = ROICoordinate(), x = 0, y = 0, width = 0, height = 0):
372 ShapeData.__init__(self); 373 self.x = rdouble(x); 374 self.y = rdouble(y); 375 self.width = rdouble(width); 376 self.height = rdouble(height); 377 self.setCoord(roicoord);
378 379 ## 380 # overridden, @See ShapeData#setGeometry 381 #
382 - def setGeometry(self, rectangle):
383 rectangle.setTheZ(self.coord.theZ); 384 rectangle.setTheT(self.coord.theZ); 385 rectangle.setX(self.x); 386 rectangle.setY(self.y); 387 rectangle.setWidth(self.width); 388 rectangle.setHeight(self.height);
389 390 ## 391 # overridden, @See ShapeData#getGeometryFromROI 392 #
393 - def getGeometryFromROI(self, roi):
394 self.x = roi.getX(); 395 self.y = roi.getY(); 396 self.width = roi.getWidth(); 397 self.height = roi.getHeight();
398 399 ## 400 # overridden, @See ShapeData#createBaseType 401 #
402 - def createBaseType(self):
403 return RectI();
404 405 ## 406 # overridden, @See ShapeData#acceptVisitor 407 #
408 - def acceptVisitor(self, visitor):
409 visitor.drawRectangle(self.x, self.y, self.width, self.height, self.shapeSettings.getSettings());
410 ## 411 # The LineData class contains all the manipulation and create of LineI 412 # types. 413 # It also accepts the ROIDrawingUtils visitor for drawing lines. 414 #
415 -class LineData(ShapeData, ROIDrawingI):
416 417 ## 418 # Constructor for LineData object. 419 # @param roicoord The ROICoordinate of the object (default: 0,0) 420 # @param x1 The first x coordinate of the shape. 421 # @param y1 The first y coordinate of the shape. 422 # @param x2 The second x coordinate of the shape. 423 # @param y2 The second y coordinate of the shape.
424 - def __init__(self, roicoord = ROICoordinate(), x1 = 0, y1 = 0, x2 = 0, y2 = 0):
425 ShapeData.__init__(self); 426 self.x1 = rdouble(x1); 427 self.y1 = rdouble(y1); 428 self.x2 = rdouble(x2); 429 self.y2 = rdouble(y2); 430 self.setCoord(roicoord);
431 432 ## 433 # overridden, @See ShapeData#setGeometry 434 #
435 - def setGeometry(self, line):
436 line.setTheZ(self.coord.theZ); 437 line.setTheT(self.coord.theZ); 438 line.setX1(self.x1); 439 line.setY1(self.y1); 440 line.setX2(self.x2); 441 line.setY2(self.y2);
442 443 ## 444 # overridden, @See ShapeData#getGeometryFromROI 445 #
446 - def getGeometryFromROI(self, roi):
447 self.x1 = roi.getX1(); 448 self.y1 = roi.getY1(); 449 self.x2 = roi.getX2(); 450 self.y2 = roi.getY2();
451 452 ## 453 # overridden, @See ShapeData#createBaseType 454 #
455 - def createBaseType(self):
456 return LineI();
457 458 ## 459 # overridden, @See ShapeData#acceptVisitor 460 #
461 - def acceptVisitor(self, visitor):
462 visitor.drawLine(self.x1.getValue(), self.y1.getValue(), self.x2.getValue(), self.y2.getValue(), self.shapeSettings.getSettings());
463 464 ## 465 # The MaskData class contains all the manipulation and create of MaskI 466 # types. 467 # It also accepts the ROIDrawingUtils visitor for drawing masks. 468 #
469 -class MaskData(ShapeData, ROIDrawingI):
470 471 ## 472 # Constructor for MaskData object. 473 # @param roicoord The ROICoordinate of the object (default: 0,0) 474 # @param bytes The mask data. 475 # @param x The top left x - coordinate of the shape. 476 # @param y The top left y - coordinate of the shape. 477 # @param width The width of the shape. 478 # @param height The height of the shape.
479 - def __init__(self, roicoord = ROICoordinate(), bytes = None, x = 0, y = 0, width = 0, height = 0):
480 ShapeData.__init__(self); 481 self.x = rdouble(x); 482 self.y = rdouble(y); 483 self.width = rdouble(width); 484 self.height = rdouble(height); 485 self.bytesdata = bytes; 486 self.setCoord(roicoord);
487 488 ## 489 # overridden, @See ShapeData#setGeometry 490 #
491 - def setGeometry(self, mask):
492 mask.setTheZ(self.coord.theZ); 493 mask.setTheT(self.coord.theZ); 494 mask.setX(self.x); 495 mask.setY(self.y); 496 mask.setWidth(self.width); 497 mask.setHeight(self.height); 498 mask.setBytes(self.bytedata);
499 500 ## 501 # overridden, @See ShapeData#getGeometryFromROI 502 #
503 - def getGeometryFromROI(self, roi):
504 self.x = roi.getX(); 505 self.y = roi.getY(); 506 self.width = roi.getWidth(); 507 self.height = roi.getHeight(); 508 self.bytesdata = roi.getBytes();
509 510 ## 511 # overridden, @See ShapeData#createBaseType 512 #
513 - def createBaseType(self):
514 return MaskI();
515 516 ## 517 # overridden, @See ShapeData#acceptVisitor 518 #
519 - def acceptVisitor(self, visitor):
520 visitor.drawMask(self.x.getValue(), self.y.getValue(), self.width.getValue(), self.height.getValue(), self.bytesdata, self.shapeSettings.getSettings());
521 522 ## 523 # The PointData class contains all the manipulation and create of PointI 524 # types. 525 # It also accepts the ROIDrawingUtils visitor for drawing points. 526 #
527 -class PointData(ShapeData, ROIDrawingI):
528 529 ## 530 # Constructor for PointData object. 531 # @param roicoord The ROICoordinate of the object (default: 0,0) 532 # @param x The x coordinate of the shape. 533 # @param y The y coordinate of the shape.
534 - def __init__(self, roicoord = ROICoordinate(), x = 0, y = 0):
535 ShapeData.__init__(self); 536 self.x = rdouble(x); 537 self.y = rdouble(y); 538 self.setCoord(roicoord);
539 540 ## 541 # overridden, @See ShapeData#setGeometry 542 #
543 - def setGeometry(self, point):
544 point.setTheZ(self.coord.theZ); 545 point.setTheT(self.coord.theZ); 546 point.setX(self.x); 547 point.setY(self.y);
548 549 ## 550 # overridden, @See ShapeData#getGeometryFromROI 551 #
552 - def getGeometryFromROI(self, roi):
553 self.x = roi.getX(); 554 self.y = roi.getY();
555 556 ## 557 # overridden, @See ShapeData#createBaseType 558 #
559 - def createBaseType(self):
560 return PointI();
561 562 ## 563 # overridden, @See ShapeData#acceptVisitor 564 #
565 - def acceptVisitor(self, visitor):
566 visitor.drawEllipse(self.x.getValue(), self.y.getValue(), 3, 3, self.shapeSettings.getSettings());
567 568 ## 569 # The PolygonData class contains all the manipulation and create of PolygonI 570 # types. 571 # It also accepts the ROIDrawingUtils visitor for drawing polygons. 572 #
573 -class PolygonData(ShapeData, ROIDrawingI):
574 575 ## 576 # Constructor for PolygonData object. 577 # @param roicoord The ROICoordinate of the object (default: 0,0) 578 # @param pointList The list of points that make up the polygon, as pairs [x1, y1, x2, y2 ..].
579 - def __init__(self, roicoord = ROICoordinate(), pointsList = [0,0]):
580 ShapeData.__init__(self); 581 self.points = rstring(self.listToString(pointsList)); 582 self.setCoord(roicoord);
583 584 ## 585 # overridden, @See ShapeData#setGeometry 586 #
587 - def setGeometry(self, polygon):
588 polygon.setTheZ(self.coord.theZ); 589 polygon.setTheT(self.coord.theZ); 590 polygon.setPoints(self.points);
591 592 ## 593 # overridden, @See ShapeData#getGeometryFromROI 594 #
595 - def getGeometryFromROI(self, roi):
596 self.points = roi.getPoints();
597 598 ## 599 # Convert a pointsList[x1,y1,x2,y2..] to a string. 600 # @param pointsList The list of points to convert. 601 # @return The pointsList converted to a string.
602 - def listToString(self, pointsList):
603 string = ''; 604 cnt = 0; 605 for element in pointsList: 606 if(cnt!=0): 607 string = string + ','; 608 cnt += 1; 609 string = string + str(element); 610 return string;
611 612 ## 613 # Convert a string of points to a tuple list [(x1,y1),(x2,y2)..]. 614 # @param pointString The string to convert. 615 # @return The tuple list converted from a string.
616 - def stringToTupleList(self, pointString):
617 elements = []; 618 list = pointString.split(','); 619 numTokens = len(list); 620 for tokenPair in range(0,numTokens/2): 621 elements.append((int(list[tokenPair*2]), int(list[tokenPair*2+1]))); 622 return elements;
623 624 ## 625 # overridden, @See ShapeData#createBaseType 626 #
627 - def createBaseType(self):
628 return PolygonI();
629 630 ## 631 # overridden, @See ShapeData#acceptVisitor 632 #
633 - def acceptVisitor(self, visitor):
634 visitor.drawPolygon(self.stringToTupleList(self.points.getValue()), self.shapeSettings.getSettings());
635 636 ## 637 # The PolylineData class contains all the manipulation and create of PolylineI 638 # types. 639 # It also accepts the ROIDrawingUtils visitor for drawing polylines. 640 #
641 -class PolylineData(ShapeData, ROIDrawingI):
642 643 ## 644 # Constructor for PolylineData object. 645 # @param roicoord The ROICoordinate of the object (default: 0,0) 646 # @param pointList The list of points that make up the polygon, as pairs [x1, y1, x2, y2 ..].
647 - def __init__(self, roicoord = ROICoordinate(), pointsList = [0,0]):
648 ShapeData.__init__(self); 649 self.points = rstring(self.listToString(pointsList)); 650 self.setCoord(roicoord);
651 652 ## 653 # overridden, @See ShapeData#setGeometry 654 #
655 - def setGeometry(self, point):
656 point.setTheZ(self.coord.theZ); 657 point.setTheT(self.coord.theZ); 658 point.setPoints(self.points);
659 660 ## 661 # overridden, @See ShapeData#getGeometryFromROI 662 #
663 - def getGeometryFromROI(self, roi):
664 self.points = roi.getPoints();
665 666 ## 667 # Convert a pointsList[x1,y1,x2,y2..] to a string. 668 # @param pointsList The list of points to convert. 669 # @return The pointsList converted to a string.
670 - def listToString(self, pointsList):
671 string = ''; 672 cnt = 0; 673 for element in pointsList: 674 if(cnt > 0): 675 string = string + ','; 676 string = string + str(element); 677 cnt+=1; 678 return string;
679 680 ## 681 # Convert a string of points to a tuple list [(x1,y1),(x2,y2)..]. 682 # @param pointString The string to convert. 683 # @return The tuple list converted from a string.
684 - def stringToTupleList(self, pointString):
685 elements = []; 686 list = pointString.split(','); 687 numTokens = len(list); 688 for tokenPair in range(0,numTokens/2): 689 elements.append((int(list[tokenPair*2]), int(list[tokenPair*2+1]))); 690 return elements;
691 692 ## 693 # overridden, @See ShapeData#createBaseType 694 #
695 - def createBaseType(self):
696 return PolylineI();
697 698 ## 699 # overridden, @See ShapeData#acceptVisitor 700 #
701 - def acceptVisitor(self, visitor):
702 visitor.drawPolyline(self.stringToTupleList(self.points.getValue()), self.shapeSettings.getSettings());
703