def genDia(): x = random.randint(llim // 2, rlim // 2) y = random.randint(llim // 2, rlim // 2) AB = geo.Vector(x, y) BC = geo.Vector(x, -y) AD = BC DC = AB minx = llim - AB.x if llim > minx: minx = llim maxx = rlim - AB.x if rlim < maxx: maxx = rlim miny = llim - AB.y if llim > miny: miny = llim maxy = rlim - AB.y if rlim < maxy: maxy = rlim A = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OB = geo.Vector(A.x, A.y) + AB B = geo.Point(OB.x, OB.y) OC = OB + BC OD = geo.Vector(A.x, A.y) + AD C = geo.Point(OC.x, OC.y) D = geo.Point(OD.x, OD.y) buf = ["A : " + str(A), "B : " + str(B), "C : " + str(C), "D : " + str(D)] tasks.update({"Diamond": buf})
def get_expected_hull(): return [ geo.Point(-2, -2), geo.Point(2, -2), geo.Point(7, 2), geo.Point(4, 6), geo.Point(-3, 2) ]
def genCom(): x = random.randint(llim + 1, rlim - 1) y = random.randint(llim + 1, rlim - 1) x2 = random.randint(llim + 1, rlim - 1) y2 = random.randint(llim + 1, rlim - 1) while (x == x2) and (y == y2): x2 = random.randint(llim + 1, rlim - 1) y2 = random.randint(llim + 1, rlim - 1) AB = geo.Vector(x, y) DC = geo.Vector(x2, y2) minx = llim - AB.x if llim > minx: minx = llim maxx = rlim - AB.x if rlim < maxx: maxx = rlim miny = llim - AB.y if llim > miny: miny = llim maxy = rlim - AB.y if rlim < maxy: maxy = rlim A = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OB = geo.Vector(A.x, A.y) + AB B = geo.Point(OB.x, OB.y) x = random.randint(llim - A.x, rlim - A.x) y = random.randint(llim - A.y, rlim - A.y) x2 = random.randint(llim - B.x, rlim - B.x) y2 = random.randint(llim - B.y, rlim - B.y) while (x == x2) and (y == y2): x2 = random.randint(llim - B.x, rlim - B.x) y2 = random.randint(llim - B.y, rlim - B.y) AD = geo.Vector(x, y) BC = geo.Vector(x2, y2) OC = OB + BC OD = geo.Vector(A.x, A.y) + AD C = geo.Point(OC.x, OC.y) D = geo.Point(OD.x, OD.y) buf = ["A : " + str(A), "B : " + str(B), "C : " + str(C), "D : " + str(D)] tasks.update({"Common": buf})
def on_canvas_mouse_release_event(self, event): mouse_point = self.window_to_point(event.pos()) found = False if self.fold: line = geoutil.line.perpendicular(self.fold, geo.Point(0.5, 0.5)) point = geoutil.line.intersect(line, self.fold) threshold = self.selection_threshold() if (mouse_point - point).magnitude2() < threshold * threshold: self.fold = geo.Line(-self.fold.normal, -self.fold.offset) found = True if not found: if self.highlight: if self.highlight in self.selected: self.selected.remove(self.highlight) else: if self.num_selected(type(self.highlight)) < 2: self.selected.append(self.highlight) self.highlight = None else: self.selected.clear() self.ui.canvas.update() self.update_actions()
def genRect(): k = random.randint(2, (rlim - llim - 1) // 2) if random.randint(0, 1) == 1: k *= -1 x = random.randint(llim // abs(k), rlim // abs(k)) y = random.randint(llim // abs(k), rlim // abs(k)) y2 = x * k x2 = -y * k if random.randint(0, 1) == 1: AD = geo.Vector(x, y) BC = AD AB = geo.Vector(x2, y2) DC = AB else: AB = geo.Vector(x, y) DC = AB AD = geo.Vector(x2, y2) BC = AD minx = llim - AB.x if llim > minx: minx = llim maxx = rlim - AB.x if rlim < maxx: maxx = rlim miny = llim - AB.y if llim > miny: miny = llim maxy = rlim - AB.y if rlim < maxy: maxy = rlim A = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OB = geo.Vector(A.x, A.y) + AB B = geo.Point(OB.x, OB.y) OC = OB + BC OD = geo.Vector(A.x, A.y) + AD C = geo.Point(OC.x, OC.y) D = geo.Point(OD.x, OD.y) if random.randint(0, 1) == 1: AB = geo.Vector(x, y) DC = AB buf = ["A : " + str(A), "B : " + str(B), "C : " + str(C), "D : " + str(D)] tasks.update({"Rectangle": buf})
def test_get_total_perimeter_of_rectangles(self): r1 = shapes.Rectangle(geo.Point(1, 1), geo.Point(6, 4)) r2 = shapes.Rectangle(geo.Point(5, 0), geo.Point(8, 2)) r3 = shapes.Rectangle(geo.Point(7, 1), geo.Point(9, 4)) r4 = shapes.Rectangle(geo.Point(4, 3), geo.Point(10, 6)) actual = shapes.get_total_perimeter_of_rectangles([r1, r2, r3, r4]) self.assertEqual(actual, 34)
def transformed_points(self): points = [] for point in self.points: cos = math.cos(self.rotation) sin = math.sin(self.rotation) x = point.x * cos - point.y * sin + self.position.x y = point.x * sin + point.y * cos + self.position.y points.append(geo.Point(x, y)) return points
def __init__(self, parent=None): super(Window, self).__init__(parent) self.ui = Ui_MainWindow() self.ui.setupUi(self) self.ui.canvas.paintEvent = self.on_canvas_paint_event self.ui.canvas.mouseReleaseEvent = self.on_canvas_mouse_release_event self.ui.canvas.mouseMoveEvent = self.on_canvas_mouse_move_event self.ui.scrollArea.resizeEvent = self.on_scroll_area_resize_event self.ui.actionZoomIn.triggered.connect(self.on_action_zoom_in) self.ui.actionZoomOut.triggered.connect(self.on_action_zoom_out) self.ui.actionPoints.triggered.connect(self.on_action_points) self.ui.actionPointPoint.triggered.connect(self.on_action_point_point) self.ui.actionLineLine.triggered.connect(self.on_action_line_line) self.ui.actionLinePoint.triggered.connect(self.on_action_line_point) self.ui.actionPointPointLine.triggered.connect( self.on_action_point_point_line) self.ui.actionLinePointLine.triggered.connect( self.on_action_line_point_line) self.ui.actionValleyFold.triggered.connect(self.on_action_valley_fold) self.ui.actionExecuteFold.triggered.connect( self.on_action_execute_fold) self.ui.canvas.setMouseTracking(True) self.zoom = 1 points = [ geo.Point(0, 0), geo.Point(0, 1), geo.Point(1, 1), geo.Point(1, 0) ] polygon = geo.Polygon(points) self.sheet = paper.Sheet(polygon) self.highlight = None self.selected = [] self.lines = [] self.intersections = [] self.fold = None self.update_actions()
def createVehicle(self, sInf, dInf, timeStep): """ create a vehicle object from aimsun static and dynamic information objects, and the simulation timeStep """ # fetch static vehicle information vID = sInf.idVeh (vLength, vWidth) = (sInf.length, sInf.width) (vMaxSpeed, vMaxDecel, vMaxAccel) = (sInf.maxDesiredSpeed, -sInf.maxDeceleration, sInf.maxAcceleration) # fetch the vehicle type and emission class cat, vehicleClass = self.getVehicleType(vID, vLength, vWidth) # calculate position (middle point) and direction (bearing and gradient) of vehicle vPosFront = geo.Point(dInf.xCurrentPos, dInf.yCurrentPos, dInf.zCurrentPos) vPosBack = geo.Point(dInf.xCurrentPosBack, dInf.yCurrentPosBack, dInf.zCurrentPosBack) vPosition = vPosFront.middle(vPosBack) vDirection = geo.directionFromTo(vPosBack, vPosFront) # fetch speed [km/h] and acceleration [m/s^2] vSpeed = dInf.CurrentSpeed vAcceleration = (dInf.CurrentSpeed - dInf.PreviousSpeed)/(3.6*timeStep) # finally, construct vehicle return vehicleClass(vid = vID, length = vLength, width = vWidth, cat = cat, maxspeed = vMaxSpeed, maxdecel = vMaxDecel, maxaccel = vMaxAccel, position = vPosition, direction = vDirection, speed = vSpeed, acceleration = vAcceleration)
def test_segments_intersect(self): seg1 = shapes.Segment(geo.Point(1, 1), geo.Point(4, 4)) seg2 = shapes.Segment(geo.Point(3, 2), geo.Point(5, 2)) actual = shapes.segments_intersect(seg1, seg2) self.assertEquals(actual, False) seg2 = shapes.Segment(geo.Point(3, 2), geo.Point(1, 3)) actual = shapes.segments_intersect(seg1, seg2) self.assertEquals(actual, True) seg2 = shapes.Segment(geo.Point(4, 4), geo.Point(5, 2)) actual = shapes.segments_intersect(seg1, seg2) self.assertEquals(actual, True)
def create_simulator(): sim = simulation.Simulator() sim.add_polygon( simulation.Polygon(geo.Point(-3, 2), 30 * 3.14 / 180, [ geo.Point(1, 1), geo.Point(-1, 1), geo.Point(-1, -1), geo.Point(1, -1) ], 1, 2.0 / 3.0, geo.Vector(4, 0), geo.Vector(0, 0, 2 * 3.14))) sim.add_polygon( simulation.Polygon(geo.Point(5, 0), 90 * 3.14 / 180, [ geo.Point(3, 1), geo.Point(-3, 1), geo.Point(-3, -1), geo.Point(3, -1) ], 3, 10, geo.Vector(0, 0), geo.Vector(0, 0, 3.14))) return sim
def intersect(line0, line1): det = line0.normal.x * line1.normal.y - line0.normal.y * line1.normal.x xdet = line0.offset * line1.normal.y - line0.normal.y * line1.offset ydet = line0.normal.x * line1.offset - line0.offset * line1.normal.x if abs(xdet) < abs(MAX_DISTANCE * det) and abs(ydet) < abs( MAX_DISTANCE * det): x = xdet / det y = ydet / det return geo.Point(x, y) else: return None
def genTrap(): k = random.randint(2, (rlim - llim) // 4) AB = geo.Vector(random.randint(-((rlim - llim) // k), (rlim - llim) // k), random.randint(-((rlim - llim) // k), (rlim - llim) // k)) DC = AB * k minx = llim - AB.x if llim > minx: minx = llim maxx = rlim - AB.x if rlim < maxx: maxx = rlim miny = llim - AB.y if llim > miny: miny = llim maxy = rlim - AB.y if rlim < maxy: maxy = rlim A = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OB = geo.Vector(A.x, A.y) + AB B = geo.Point(OB.x, OB.y) minx = llim - DC.x if llim > minx: minx = llim maxx = rlim - DC.x if rlim < maxx: maxx = rlim miny = llim - DC.y if llim > miny: miny = llim maxy = rlim - DC.y if rlim < maxy: maxy = rlim D = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OC = geo.Vector(D.x, D.y) + DC C = geo.Point(OC.x, OC.y) buf = ["A : " + str(A), "B : " + str(B), "C : " + str(C), "D : " + str(D)] tasks.update({"Trapeze": buf})
def support(self, points, direction): max_point = None max_index = -1 max_distance = 0 for i in range(0, len(points)): point = points[i] v = point - geo.Point(0, 0) distance = v * direction if max_point is None or distance > max_distance: max_point = point max_distance = distance max_index = i return (max_point, max_index)
def genSqr(): x = random.randint(llim // 2, rlim // 2) y = random.randint(llim // 2, rlim // 2) if random.randint(0, 1) == 1: y2 = x x2 = -y else: y2 = -x x2 = y if random.randint(0, 1) == 1: AD = geo.Vector(x, y) BC = AD AB = geo.Vector(x2, y2) DC = AB else: AB = geo.Vector(x, y) DC = AB AD = geo.Vector(x2, y2) BC = AD minx = max(llim - AB.x, llim, llim - AD.x) maxx = min(rlim - AB.x, rlim, rlim - AD.x) miny = max(llim - AB.y, llim, llim - AD.y) maxy = min(rlim - AB.y, rlim, rlim - AD.y) A = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OB = geo.Vector(A.x, A.y) + AB B = geo.Point(OB.x, OB.y) OC = OB + BC OD = geo.Vector(A.x, A.y) + AD C = geo.Point(OC.x, OC.y) D = geo.Point(OD.x, OD.y) buf = ["A : " + str(A), "B : " + str(B), "C : " + str(C), "D : " + str(D)] tasks.update({"Square": buf})
def gjk_collision(self, points1, points2): direction = geo.Vector(1, 0) points = [] points.append(self.minkowski_difference(points1, points2, direction)) points.append(self.minkowski_difference(points1, points2, -direction)) if points[0].x < 0 or points[1].x > 0: return (None, None) while True: AB = (points[1] - points[0]).normalize() AO = geo.Point(0, 0) - points[0] direction = AO - AB * (AO * AB) points.append( self.minkowski_difference(points1, points2, direction)) AC = points[2] - points[0] if AC * direction < AO * direction: return (None, None) for i in range(0, 3): C = points[i] A = points[(i + 1) % 3] B = points[(i + 2) % 3] AB = (B - A).normalize() AC = C - A AO = geo.Point(0, 0) - A direction = AO - AB * (AO * AB) if AC * direction < 0: del points[i] break else: (distance, direction) = self.epa_distance(points1, points2, points) point = self.get_collision_point(points1, points2, direction) return (point, direction)
def get_polygon(): p1 = geo.Point(0, 0) p2 = geo.Point(5, 0) p3 = geo.Point(5, 2) p4 = geo.Point(2, 2) p5 = geo.Point(2, 6) p6 = geo.Point(0, 3) return [p1, p2, p3, p4, p5, p6]
def genParal(): A = ranPFR(llim + 1, rlim - 1) B = ranPFR(llim + 1, rlim - 1) AB = geo.Vector(A, B) DC = AB minx = llim - DC.x if llim > minx: minx = llim maxx = rlim - DC.x if rlim < maxx: maxx = rlim miny = llim - DC.y if llim > miny: miny = llim maxy = rlim - DC.y if rlim < maxy: maxy = rlim D = geo.Point(random.randint(minx, maxx), random.randint(miny, maxy)) OC = geo.Vector(D.x, D.y) + DC C = geo.Point(OC.x, OC.y) buf = ["A : " + str(A), "B : " + str(B), "C : " + str(C), "D : " + str(D)] tasks.update({"Paral": buf})
def load(file, location_col, target_cols): """Load Result objects from file. file: filename of csv file to load from location_col: index of the column holding location (as "<lat>,<lon>") target_cols: indices of the columns to load questions & answers from. """ reader = csv.reader(open(file)) headers = reader.next() data = [] for line in reader: lat, lon = _readLocation(line, location_col) result = Result(geo.Point(lat, lon)) for col in target_cols: question = headers[col] result.questions[col] = question result.answers[col] = line[col] data.append(result) return data
def epa_distance(self, points1, points2, points): while True: min_point = None min_distance = 0 min_direction = None for i in range(0, len(points)): A = points[i] B = points[(i + 1) % len(points)] AB = (B - A).normalize() AO = geo.Point(0, 0) - A direction = AO - AB * (AO * AB) distance = direction.magnitude() if min_point is None or min_distance > distance: min_point = i min_distance = distance min_direction = direction new_point = self.minkowski_difference(points1, points2, -min_direction) if new_point == points[min_point] or new_point == points[ (min_point + 1) % len(points)]: return (min_distance, min_direction) else: points.insert(min_point + 1, new_point)
def testAggregatePointAllowsArrayStyleAccess(self): points = [geo.Point(x, x) for x in range(4)] aggregate = geo.AggregatePoint(9, 9, points) self.assertEqual(points[0], aggregate[0]) self.assertEqual(points[3], aggregate[3])
def test_get_area_of_intersection_rectangles(self): r1 = shapes.Rectangle(geo.Point(0, 0), geo.Point(5, 3)) r2 = shapes.Rectangle(geo.Point(3, 1), geo.Point(8, 4)) actual = shapes.get_area_of_intersection_rectangles([r1, r2]) self.assertEquals(actual, 4)
def createMetadata(s111, bname, s111meta): #if this "label" item is just for identification then it could really be anything to identify it. #metadata = {'label':os.path.splitext(os.path.basename(fname))[0].split('-',1)[1],'sources':[]} metadata = {'label': bname, 'sources': []} #After PNG is created from the data values, the accompanying JSON file #is created to help the javascript web interface know the metadata details. minLat = np.float64( s111meta.attrs.get('southBoundLatitude') ) #s111meta.southBoundLatitude ->mask.Minimum_Latitude, s111meta.northBoundLatitude ->mask.Maximum_Latitude maxLat = np.float64(s111meta.attrs.get('northBoundLatitude')) minLon = np.float64(s111meta.attrs.get('westBoundLongitude')) maxLon = np.float64(s111meta.attrs.get('eastBoundLongitude')) delta_lon = s111meta.attrs.get('gridSpacingLongitudinal') #step size delta_lat = s111meta.attrs.get('gridSpacingLatitudinal') #step size #maxAbsLat = max(abs(float(mask.Minimum_Latitude)),abs(float(mask.Maximum_Latitude))) maxAbsLat = max(abs(minLat), abs(maxLat)) p1 = geo.Point(0, maxAbsLat) p2 = geo.Point(delta_lon, maxAbsLat - delta_lat) metadata['density_meters'] = geo.sphericalEarth.distanceCourseFromDeg( p1, p2)['distance'] s = {'src': getOutfn(bname)} s['type'] = 'grid' s['georeference'] = {} s['georeference']['bounds'] = {} s['georeference']['bounds']['min'] = {'x': minLon, 'y': minLat} s['georeference']['bounds']['max'] = {'x': maxLon, 'y': maxLat} s['georeference']['projection'] = 'WGS84' s['georeference']['density'] = { 'x': np.float64(delta_lon), 'y': np.float64(delta_lat) } s['georeference']['origin'] = {"x": minLon, "y": maxLat} s['georeference']['stepSize'] = { "x": np.float64(delta_lon), "y": -np.float64(delta_lat) } s['mask'] = 'mask' s['definition'] = {} s['definition']['u'] = { "highBit": 31, "lowBit": 20, "base": -20.48, "scale": 0.01 } s['definition']['v'] = { "highBit": 19, "lowBit": 8, "base": -20.48, "scale": 0.01 } s['definition']['mask'] = { "highBit": 7, "lowBit": 0, "base": 0, "scale": 1 } metadata['sources'].append(s) return metadata
def testAggregatePointHasLength(self): points = [geo.Point(x, x) for x in range(4)] aggregate = geo.AggregatePoint(9, 9, points) self.assertEqual(len(points), len(aggregate))
def makePoints(self, *coordinates): """Return a list of geo.Point() objects for the given coordinates""" return [geo.Point(lat, lon) for lat, lon in coordinates]
def on_canvas_paint_event(self, event): painter = QtGui.QPainter(self.ui.canvas) painter.setRenderHint(QtGui.QPainter.Antialiasing) def draw_segment(segment): draw_points = [ self.point_to_window(point) for point in segment.points() ] painter.drawLine(*draw_points) def draw_point(point): painter.drawEllipse(self.point_to_window(point), POINT_SIZE, POINT_SIZE) def draw_line(line): min = self.window_to_point(QtCore.QPoint(0, 0)) max = self.window_to_point( QtCore.QPoint(self.ui.canvas.width(), self.ui.canvas.height())) if abs(line.normal.x) > abs(line.normal.y): minline = geoutil.line.from_point_normal(min, geo.Vector(0, 1)) maxline = geoutil.line.from_point_normal( max, geo.Vector(0, -1)) else: minline = geoutil.line.from_point_normal(min, geo.Vector(1, 0)) maxline = geoutil.line.from_point_normal( max, geo.Vector(-1, 0)) minpoint = geoutil.line.intersect(line, minline) maxpoint = geoutil.line.intersect(line, maxline) points = [minpoint, maxpoint] draw_points = [self.point_to_window(point) for point in points] painter.drawLine(*draw_points) def draw_polygon(polygon): draw_points = [ self.point_to_window(point) for point in polygon.points ] painter.drawPolygon(draw_points) pen = QtGui.QPen(EDGE_COLOR, LINE_WIDTH, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin) painter.setPen(pen) for layer in self.sheet.layers: for facet in layer.facets: brush = QtGui.QBrush(PAPER_COLORS[facet.parity]) painter.setBrush(brush) draw_polygon(facet.polygon) highlight = self.highlight if highlight: if highlight in self.selected or self.num_selected( type(highlight)) == 2: highlight = None pen = QtGui.QPen(LINE_COLOR, LINE_WIDTH, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin) painter.setPen(pen) for line in self.lines: draw_line(line) pen = QtGui.QPen(FOLD_COLOR, FOLD_WIDTH, Qt.DashLine, Qt.SquareCap, Qt.MiterJoin) painter.setPen(pen) if self.fold: draw_line(self.fold) line = geoutil.line.perpendicular(self.fold, geo.Point(0.5, 0.5)) point = self.point_to_window( geoutil.line.intersect(line, self.fold)) vec = QtCore.QPoint(self.fold.normal.x * 20, self.fold.normal.y * 20) p = geoutil.vector.perpendicular(self.fold.normal) perp_vec = QtCore.QPoint(p.x * 5, p.y * 5) norm_vec = QtCore.QPoint(self.fold.normal.x * 5, self.fold.normal.y * 5) pen = QtGui.QPen(QtGui.QColor(0, 0, 0), 2, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin) painter.setPen(pen) painter.drawLine(point - vec, point + vec) painter.drawLine(point + vec, point + vec - norm_vec - perp_vec) painter.drawLine(point + vec, point + vec - norm_vec + perp_vec) idx = 0 for selected in self.selected: if not isinstance(selected, geo.Line): continue pen = QtGui.QPen(SELECTED_LINE_COLORS[idx], LINE_WIDTH_SELECTED, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin) painter.setPen(pen) draw_line(selected) idx += 1 idx = 0 painter.setPen(Qt.NoPen) for selected in self.selected: if not isinstance(selected, geo.Point): continue brush = QtGui.QBrush(SELECTED_POINT_COLORS[idx]) painter.setBrush(brush) draw_point(selected) idx += 1 if highlight: if isinstance(highlight, geo.Line): pen = QtGui.QPen(HIGHLIGHT_COLOR, LINE_WIDTH_SELECTED, Qt.SolidLine, Qt.SquareCap, Qt.MiterJoin) painter.setPen(pen) draw_line(highlight) elif isinstance(highlight, geo.Point): brush = QtGui.QBrush(HIGHLIGHT_COLOR) painter.setBrush(brush) painter.setPen(Qt.NoPen) draw_point(highlight)
def test_get_area_of_triangle(self): area = shapes.get_area_of_triangle(geo.Point(0, 0), geo.Point(5, 0), geo.Point(2, 10)) self.assertEqual(area, 25)
def yes_no_to_boolean(yes_no_point): """ Make a geo.Point containing boolean data from one containing "yes" or "no" strings.""" bool_point = geo.Point(yes_no_point.lat, yes_no_point.lon) bool_point.value = _convert_yes_no(yes_no_point.value) return bool_point
#!/usr/bin/python3 import line import geo import delaunay import random as r from vectangle import Vectorizer p1 = geo.Point(100, 100) p2 = geo.Point(150, 150) p3 = geo.Point(100, 150) p4 = geo.Point(150, 150) p5 = geo.Point(125, 130) p6 = geo.Point(130, 125) p7 = geo.Point(120, 125) p8 = geo.Point(125, 120) colors = [ '#FFFFFF', '#C0C0C0', '#808080', '#000000', '#FF0000', '#800000', '#FFFF00', '#808000', '#00FF00', '#008000', '#00FFFF', '#008080', '#0000FF', '#000080', '#FF00FF', '#800080' ] d = delaunay.Delaunay(200, 200) d.add_points([p5, p6, p7, p8]) for tri in d.tris: print(tri) vec = Vectorizer('15cm', '15cm') for tri in d.tris:
def window_to_point(self, point): size = self.canvas_size() return geo.Point((point.x() - MARGIN) / (size - 2 * MARGIN), (point.y() - MARGIN) / (size - 2 * MARGIN))