mathmaker
0.4(alpha)
|
00001 # -*- coding: utf-8 -*- 00002 00003 # Mathmaker creates automatically maths exercises sheets with their answers 00004 # Copyright 2006-2014 Nicolas Hainaux <nico_h@users.sourceforge.net> 00005 00006 # This file is part of Mathmaker. 00007 00008 # Mathmaker is free software; you can redistribute it and/or modify 00009 # it under the terms of the GNU General Public License as published by 00010 # the Free Software Foundation; either version 3 of the License, or 00011 # any later version. 00012 00013 # Mathmaker is distributed in the hope that it will be useful, 00014 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 # GNU General Public License for more details. 00017 00018 # You should have received a copy of the GNU General Public License 00019 # along with Mathmaker; if not, write to the Free Software 00020 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00021 00022 # ------------------------------------------------------------------------------ 00023 # -------------------------------------------------------------------------- 00024 # ------------------------------------------------------------------------------ 00025 ## 00026 # @package core.geometry 00027 # @brief Mathematical geometrical objects. 00028 00029 import math 00030 import locale 00031 from decimal import * 00032 from base import * 00033 from base_geometry import * 00034 from lib import * 00035 from lib import randomly 00036 from lib.maths_lib import * 00037 from core.calculus import * 00038 from lib.common import cfg 00039 00040 if debug.ENABLED: 00041 from lib.common import latex 00042 import machine 00043 00044 markup_choice = cfg.get_value_from_file('MARKUP', 'USE') 00045 00046 if markup_choice == 'latex': 00047 from lib.common.latex import MARKUP 00048 00049 try: 00050 locale.setlocale(locale.LC_ALL, default.LANGUAGE + '.' + default.ENCODING) 00051 except: 00052 locale.setlocale(locale.LC_ALL, '') 00053 00054 # GLOBAL 00055 #expression_begins = True 00056 00057 00058 00059 00060 00061 00062 # ------------------------------------------------------------------------------ 00063 # -------------------------------------------------------------------------- 00064 # ------------------------------------------------------------------------------ 00065 ## 00066 # @class Triangle 00067 # @brief 00068 class Triangle(Drawable): 00069 00070 00071 00072 00073 00074 # -------------------------------------------------------------------------- 00075 ## 00076 # @brief Constructor. 00077 # @param arg : Triangle | 00078 # ((str, str, str), (not implemented yet)'sketch' 00079 # OR : {'side0':nb0, 'angle1':nb1, 'side1':nb2} 00080 # OR : (not implemented yet){'side0':nb0, 'side1':nb1, 'side2':nb2} 00081 # OR : (not implemented yet) etc. 00082 # ) 00083 # NB : the three str will be the vertices' names 00084 # NB : 'sketch' will just choose (reasonnably) random values 00085 # @param options 00086 # Options details : 00087 # - rotate_around_gravity_center = 'no'|'any'|nb 00088 # (nb being the angle, 00089 # defaulting to 'any' if sketch or 'no' if not a sketch) 00090 # FOLLOWING STUFF CAN BE REPLACED BY SETTERS 00091 # - label_side0, label_side1, label_side2, 00092 # - mark_side0, mark_side1, mark_side2, 00093 # - label_angle0, label_angle1, label_angle2, 00094 # - mark_angle0, mark_angle1, mark_angle2, 00095 # @warning Might raise... 00096 def __init__(self, arg, **options): 00097 if not (isinstance(arg, Triangle) or type(arg) == tuple): 00098 raise error.WrongArgument(' Triangle|tuple ', 00099 str(type(arg))) 00100 00101 self._vertices = [None, None, None] 00102 self._sides = [None, None, None] 00103 self._angles = [None, None, None] 00104 self._name = "" 00105 self._rotation_angle = 0 00106 00107 if type(arg) == tuple: 00108 if not len(arg) == 2: 00109 raise error.WrongArgument(' tuple of length 2 ', 00110 ' tuple of length ' \ 00111 + str(len(arg)) 00112 ) 00113 00114 vertices_names = arg[0] 00115 construction_data = arg[1] 00116 00117 if not type(vertices_names) == tuple: 00118 raise error.WrongArgument(' a tuple ', str(vertices_names)) 00119 00120 if not type(vertices_names[0]) == str \ 00121 and type(vertices_names[1]) == str \ 00122 and type(vertices_names[2]) == str: 00123 #___ 00124 raise error.WrongArgument(' three strings ', 00125 ' one of them at least is not a string') 00126 00127 if not (construction_data == 'sketch' \ 00128 or (type(construction_data) == dict \ 00129 and 'side0' in construction_data \ 00130 and is_.a_number(construction_data['side0']) \ 00131 and (('side1' in construction_data \ 00132 and is_.a_number(construction_data['side1']) \ 00133 ) \ 00134 or \ 00135 (('angle1' in construction_data \ 00136 and is_.a_number(construction_data['angle1']) \ 00137 ) \ 00138 ) \ 00139 ) \ 00140 ) \ 00141 ): 00142 #___ 00143 raise error.WrongArgument(" 'sketch' | " \ 00144 + "{'side0':nb0, 'angle1':nb1, 'side1':nb2} | ", 00145 str(construction_data)) 00146 00147 start_vertex = [None, None, None] 00148 00149 side0_length = construction_data['side0'] 00150 side1_length = construction_data['side1'] 00151 00152 if 'rotate_around_isobarycenter' in options: 00153 if options['rotate_around_isobarycenter'] == 'randomly': 00154 self._rotation_angle = randomly.integer(0, 35) * 10 00155 elif is_.a_number(options['rotate_around_isobarycenter']): 00156 self._rotation_angle = \ 00157 options['rotate_around_isobarycenter'] 00158 00159 start_vertex[0] = Point([vertices_names[0], 00160 (0, 0) 00161 ] 00162 ) 00163 start_vertex[1] = Point([vertices_names[1], 00164 (side0_length, 0) 00165 ] 00166 ) 00167 start_vertex[2] = Point([vertices_names[2], 00168 (side0_length \ 00169 - side1_length*Decimal(str(math.cos(\ 00170 deg_to_rad(construction_data['angle1'])))), 00171 side1_length*Decimal(str(math.sin( \ 00172 deg_to_rad(construction_data['angle1'])))) 00173 ) 00174 ] 00175 ) 00176 00177 if self._rotation_angle != 0: 00178 G = barycenter([start_vertex[0], 00179 start_vertex[1], 00180 start_vertex[2] 00181 ], 00182 "G" 00183 ) 00184 00185 self._vertices = (Point(\ 00186 start_vertex[0].rotate(G, 00187 self._rotation_angle, 00188 keep_name=True 00189 ) 00190 ), 00191 Point(\ 00192 start_vertex[1].rotate(G, 00193 self._rotation_angle, 00194 keep_name=True 00195 ) 00196 ), 00197 Point(\ 00198 start_vertex[2].rotate(G, 00199 self._rotation_angle, 00200 keep_name=True 00201 ) 00202 ) 00203 ) 00204 00205 else: 00206 self._vertices = (start_vertex[0].clone(), 00207 start_vertex[1].clone(), 00208 start_vertex[2].clone() 00209 ) 00210 00211 self._sides = (Segment((self._vertices[0], 00212 self._vertices[1] 00213 ) 00214 ), 00215 Segment((self._vertices[1], 00216 self._vertices[2] 00217 ) 00218 ), 00219 Segment((self._vertices[2], 00220 self._vertices[0] 00221 ) 00222 ) 00223 ) 00224 00225 self._angles[0] = Angle((self.vertex1, self.vertex0, self.vertex2)) 00226 self._angles[1] = Angle((self.vertex2, self.vertex1, self.vertex0)) 00227 self._angles[2] = Angle((self.vertex0, self.vertex2, self.vertex1)) 00228 00229 self._angles[0].set_label_display_angle(self._angles[0].measure/2) 00230 self._angles[1].set_label_display_angle(180 \ 00231 - self._angles[1].measure/2) 00232 self._angles[2].set_label_display_angle(180 \ 00233 + self._angles[0].measure \ 00234 + self._angles[2].measure/2) 00235 00236 else: 00237 # copy of a given Triangle 00238 self._vertices = [arg.vertex0.clone(), 00239 arg.vertex1.clone(), 00240 arg.vertex2.clone() 00241 ] 00242 self._rotation_angle = arg.rotation_angle 00243 self._sides = [arg.side0.clone(), 00244 arg.side1.clone(), 00245 arg.side2.clone() 00246 ] 00247 self._angles = [arg.angle0.clone(), 00248 arg.angle1.clone(), 00249 arg.angle2.clone() 00250 ] 00251 00252 self._name = self.vertex0.name + self.vertex1.name + self.vertex2.name 00253 00254 random_number = "" 00255 for i in xrange(8): 00256 random_number += str(randomly.integer(0, 9)) 00257 00258 self._filename = _("Triangle") + "_" + self.name \ 00259 + "-" + random_number 00260 00261 00262 00263 00264 00265 00266 00267 # -------------------------------------------------------------------------- 00268 ## 00269 # @brief Returns vertex0 (as a Point) 00270 def get_vertex0(self): 00271 return self._vertices[0] 00272 # -------------------------------------------------------------------------- 00273 vertex0 = property(get_vertex0, 00274 doc = "First vertex of the Triangle") 00275 00276 00277 00278 00279 00280 # -------------------------------------------------------------------------- 00281 ## 00282 # @brief Returns vertex1 (as a Point) 00283 def get_vertex1(self): 00284 return self._vertices[1] 00285 # -------------------------------------------------------------------------- 00286 vertex1 = property(get_vertex1, 00287 doc = "Second vertex of the Triangle") 00288 00289 00290 00291 00292 00293 # -------------------------------------------------------------------------- 00294 ## 00295 # @brief Returns vertex2 (as a Point) 00296 def get_vertex2(self): 00297 return self._vertices[2] 00298 # -------------------------------------------------------------------------- 00299 vertex2 = property(get_vertex2, 00300 doc = "Third vertex of the Triangle") 00301 00302 00303 00304 00305 00306 # -------------------------------------------------------------------------- 00307 ## 00308 # @brief Returns the three vertices (as a list of Points) 00309 def get_vertices(self): 00310 return self._vertices 00311 # -------------------------------------------------------------------------- 00312 vertices = property(get_vertices, 00313 doc = "The three vertices (in a list)") 00314 00315 00316 00317 00318 00319 # -------------------------------------------------------------------------- 00320 ## 00321 # @brief Returns the angle of rotation around the isobarycenter 00322 def get_rotation_angle(self): 00323 return self._rotation_angle 00324 # -------------------------------------------------------------------------- 00325 rotation_angle = property(get_rotation_angle, 00326 doc = "Angle of rotation around the isobarycenter") 00327 00328 00329 00330 00331 00332 # -------------------------------------------------------------------------- 00333 ## 00334 # @brief Returns angle0 (as an Angle) 00335 def get_angle0(self): 00336 return self._angles[0] 00337 # -------------------------------------------------------------------------- 00338 angle0 = property(get_angle0, 00339 doc = "First angle of the Triangle") 00340 00341 00342 00343 00344 00345 # -------------------------------------------------------------------------- 00346 ## 00347 # @brief Returns angle1 (as an Angle) 00348 def get_angle1(self): 00349 return self._angles[1] 00350 # -------------------------------------------------------------------------- 00351 angle1 = property(get_angle1, 00352 doc = "Second angle of the Triangle") 00353 00354 00355 00356 00357 00358 # -------------------------------------------------------------------------- 00359 ## 00360 # @brief Returns angle2 (as an Angle) 00361 def get_angle2(self): 00362 return self._angles[2] 00363 # -------------------------------------------------------------------------- 00364 angle2 = property(get_angle2, 00365 doc = "Third angle of the Triangle") 00366 00367 00368 00369 00370 00371 # -------------------------------------------------------------------------- 00372 ## 00373 # @brief Returns [angles] (as a list of Angles) 00374 def get_angles(self): 00375 return self._angles 00376 # -------------------------------------------------------------------------- 00377 angles = property(get_angles, 00378 doc = "The angles' list of the Triangle") 00379 00380 00381 00382 00383 00384 # -------------------------------------------------------------------------- 00385 ## 00386 # @brief Returns side0 (as a Segment) 00387 def get_side0(self): 00388 return self._sides[0] 00389 # -------------------------------------------------------------------------- 00390 side0 = property(get_side0, 00391 doc = "First side of the Triangle") 00392 00393 00394 00395 00396 00397 # -------------------------------------------------------------------------- 00398 ## 00399 # @brief Returns side1 (as a Segment) 00400 def get_side1(self): 00401 return self._sides[1] 00402 # -------------------------------------------------------------------------- 00403 side1 = property(get_side1, 00404 doc = "Second side of the Triangle") 00405 00406 00407 00408 00409 00410 # -------------------------------------------------------------------------- 00411 ## 00412 # @brief Returns side2 (as a Segment) 00413 def get_side2(self): 00414 return self._sides[2] 00415 # -------------------------------------------------------------------------- 00416 side2 = property(get_side2, 00417 doc = "Third side of the Triangle") 00418 00419 00420 00421 00422 00423 # -------------------------------------------------------------------------- 00424 ## 00425 # @brief Returns [sides] (as a list of Segments) 00426 def get_sides(self): 00427 return self._sides 00428 # -------------------------------------------------------------------------- 00429 sides = property(get_sides, 00430 doc = "The sides' list of the Triangle") 00431 00432 00433 00434 00435 00436 # -------------------------------------------------------------------------- 00437 ## 00438 # @brief Creates the euk string to put in the file 00439 # @param options Any options 00440 # @return The string to put in the picture file 00441 def into_euk(self, **options): 00442 box_values = self.work_out_euk_box() 00443 result = "box " + str(box_values[0]) + ", " \ 00444 + str(box_values[1]) + ", " \ 00445 + str(box_values[2]) + ", " \ 00446 + str(box_values[3]) 00447 00448 result += "\n\n" 00449 00450 for vertex in self.vertices: 00451 result += vertex.name + " = point(" + str(vertex.x) \ 00452 + ", " \ 00453 + str(vertex.y) + ")\n" 00454 00455 result += "\n\n" 00456 00457 result += "draw" 00458 00459 result += "\n " 00460 00461 result += "(" + self.vertex0.name + "." \ 00462 + self.vertex1.name + "." \ 00463 + self.vertex2.name + ")" 00464 00465 scale_factor = 1 00466 angle_correction = 0 00467 00468 sides_angles_offsets = {self.sides[0] : 0, 00469 self.sides[1] : 180 - self.angle1.measure, 00470 self.sides[2] : self.angle0.measure 00471 } 00472 00473 labels_angle_correction_signs = {self.sides[0] : "-", 00474 self.sides[1] : "-", 00475 self.sides[2] : "+" 00476 } 00477 00478 labels_ref_points = {self.sides[0] : self.vertex0.name, 00479 self.sides[1] : self.vertex1.name, 00480 self.sides[2] : self.vertex0.name 00481 } 00482 00483 00484 for side in self.sides: 00485 if side.label != None and side.label != Value(""): 00486 x = side.length 00487 scale_factor = round(Decimal(str(1.6*x)), 00488 Decimal('0.1'), 00489 rounding=ROUND_UP 00490 ) 00491 if x <= 3: 00492 angle_correction = round(Decimal(str(-8*x + 33)), 00493 Decimal('0.1'), 00494 rounding=ROUND_UP 00495 ) 00496 else: 00497 angle_correction = round(Decimal(str( \ 00498 1.1/(1-0.95*math.exp(-0.027*x)) 00499 ) 00500 ), 00501 Decimal('0.1'), 00502 rounding=ROUND_UP 00503 ) 00504 00505 label_position_angle = round(Decimal(str(self.rotation_angle))\ 00506 + \ 00507 Decimal(str(\ 00508 sides_angles_offsets[side])), 00509 Decimal('1'), 00510 rounding=ROUND_HALF_EVEN 00511 ) 00512 00513 rotate_box_angle = Decimal(label_position_angle) 00514 00515 if (rotate_box_angle >= 90 \ 00516 and rotate_box_angle <= 270): 00517 #___ 00518 rotate_box_angle -= Decimal("180") 00519 elif (rotate_box_angle <= -90 \ 00520 and rotate_box_angle >= -270): 00521 #___ 00522 rotate_box_angle += Decimal("180") 00523 00524 result += "\n " 00525 result += "$\\rotatebox{" 00526 result += str(rotate_box_angle) 00527 result += "}{" 00528 result += side.label.into_str(display_unit='yes', 00529 graphic_display='yes') 00530 result += "}$ " 00531 result += labels_ref_points[side] + " " 00532 result += str(label_position_angle) 00533 result += " " + labels_angle_correction_signs[side] + " " 00534 result += str(angle_correction) + " deg " 00535 result += str(scale_factor) 00536 result += "\n" 00537 00538 00539 for angle in self.angles: 00540 if angle.label != None and angle.label != Value(""): 00541 scale_factor = Decimal('2.7') 00542 if Decimal(str(angle.measure)) < Decimal('28.5'): 00543 scale_factor = round(Decimal('38.1')\ 00544 *pow(Decimal(str(angle.measure)), 00545 Decimal('-0.8') 00546 ), 00547 Decimal('0.01'), 00548 rounding=ROUND_HALF_UP 00549 ) 00550 00551 label_position_angle = Decimal(str(angle.label_display_angle)) \ 00552 + Decimal(str(self.rotation_angle)) 00553 rotate_box_angle = Decimal(label_position_angle) 00554 00555 if (rotate_box_angle >= 90 \ 00556 and rotate_box_angle <= 270): 00557 #___ 00558 rotate_box_angle -= Decimal("180") 00559 elif (rotate_box_angle <= -90 \ 00560 and rotate_box_angle >= -270): 00561 #___ 00562 rotate_box_angle += Decimal("180") 00563 00564 result += "\n " 00565 result += "$\\rotatebox{" 00566 result += str(rotate_box_angle) 00567 result += "}{" 00568 result += angle.label.into_str(display_unit='yes', 00569 graphic_display='yes') 00570 result += "}$ " 00571 result += angle.vertex.name + " " 00572 result += str(label_position_angle) + " deg " 00573 result += str(scale_factor) 00574 result += "\n" 00575 00576 result += "\nend" 00577 00578 result += "\n\n" 00579 00580 result += "label" 00581 00582 result += "\n" 00583 00584 for angle in self.angles: 00585 if angle.mark != "": 00586 result += " " + angle.point0.name + ", " \ 00587 + angle.vertex.name + ", " \ 00588 + angle.point2.name \ 00589 + " " \ 00590 + angle.mark 00591 result += "\n" 00592 00593 result += " " + self.vertex0.name + " " \ 00594 + str(self.rotation_angle) + " + 200 deg" 00595 00596 result += "\n" 00597 00598 result += " " + self.vertex1.name + " " \ 00599 + str(self.rotation_angle) + " - 45 deg" 00600 00601 result += "\n" 00602 00603 result += " " + self.vertex2.name + " " \ 00604 + str(self.rotation_angle) + " + 65 deg" 00605 00606 result += "\nend" 00607 00608 return result 00609 00610 00611 00612 00613 00614 # -------------------------------------------------------------------------- 00615 ## 00616 # @brief Works out the dimensions of the box 00617 # @param options Any options 00618 # @return (x1, y1, x2, y2) 00619 def work_out_euk_box(self, **options): 00620 x_list = [self.vertex0.x, 00621 self.vertex1.x, 00622 self.vertex2.x 00623 ] 00624 y_list = [self.vertex0.y, 00625 self.vertex1.y, 00626 self.vertex2.y 00627 ] 00628 00629 return (min(x_list)-Decimal("0.6"), min(y_list)-Decimal("0.6"), 00630 max(x_list)+Decimal("0.6"), max(y_list)+Decimal("0.6")) 00631 00632 00633 00634 00635 00636 00637 # ------------------------------------------------------------------------------ 00638 # -------------------------------------------------------------------------- 00639 # ------------------------------------------------------------------------------ 00640 ## 00641 # @class RightTriangle 00642 # @brief 00643 class RightTriangle(Triangle): 00644 00645 00646 00647 00648 00649 # -------------------------------------------------------------------------- 00650 ## 00651 # @brief Constructor. 00652 # @param arg : RightTriangle | 00653 # ((str, str, str), 'sketch' 00654 # OR : {'leg0' : nb0, 'leg1' : nb1} 00655 # OR : (not implemented yet){'leg0' : nb0, 'angle0' : nb1} 00656 # ) 00657 # NB : the three str will be the vertices' names 00658 # The second name will be the right corner 00659 # so, hypotenuse will be vertices_names[0] & [2] 00660 # NB : 'sketch' will just choose (reasonnably) random values 00661 # @param options 00662 # Options details : 00663 # - rotate_around_gravity_center = 'no'|'any'|nb 00664 # (nb being the angle, 00665 # defaulting to 'any' if sketch or 'no' if not a sketch) 00666 # FOLLOWING ONES HAVE BEEN REPLACED BY MATCHING SETTERS 00667 # - label_leg0, label_leg1, label_hypotenuse, 00668 # - dont_label_right_angle, label_angle0, label_angle2 00669 # @warning Might raise... 00670 def __init__(self, arg, **options): 00671 if not (isinstance(arg, RightTriangle) or type(arg) == tuple): 00672 raise error.WrongArgument(' RightTriangle|tuple ', 00673 str(type(arg))) 00674 00675 self._vertices = [None, None, None] 00676 self._rotation_angle = 0 00677 self._sides = [None, None, None] 00678 self._name = "" 00679 00680 if type(arg) == tuple: 00681 if not len(arg) == 2: 00682 raise error.WrongArgument(' tuple of length 2 ', 00683 ' tuple of length ' \ 00684 + str(len(arg)) 00685 ) 00686 vertices_names = arg[0] 00687 construction_data = arg[1] 00688 00689 if not type(vertices_names) == tuple: 00690 raise error.WrongArgument(' a tuple ', str(vertices_names)) 00691 00692 if not type(vertices_names[0]) == str \ 00693 and type(vertices_names[1]) == str \ 00694 and type(vertices_names[2]) == str: 00695 #___ 00696 raise error.WrongArgument(' three strings ', 00697 ' one of them at least is not a string') 00698 00699 rotation = 0 00700 00701 if 'rotate_around_isobarycenter' in options \ 00702 and options['rotate_around_isobarycenter'] == 'randomly': 00703 #___ 00704 rotation = randomly.integer(0, 35) * 10 00705 00706 elif 'rotate_around_isobarycenter' in options \ 00707 and is_.a_number(options['rotate_around_isobarycenter']): 00708 #___ 00709 rotation = options['rotate_around_isobarycenter'] 00710 00711 leg0_length = 0 00712 leg1_length = 0 00713 00714 if construction_data == 'sketch': 00715 leg0_length = Decimal(str(randomly.integer(35, 55)))/10 00716 leg1_length = Decimal(str(randomly.integer(7, 17))) \ 00717 / Decimal("20") * leg0_length 00718 00719 elif type(construction_data) == dict \ 00720 and 'leg0' in construction_data \ 00721 and is_.a_number(construction_data['leg0']) \ 00722 and 'leg1' in construction_data \ 00723 and is_.a_number(construction_data['leg1']): 00724 #___ 00725 leg0_length = construction_data['leg0'] 00726 leg1_length = construction_data['leg1'] 00727 00728 else: 00729 raise error.WrongArgument(" 'sketch' | " \ 00730 + "{'leg0' : nb0, 'leg1' : nb1}", 00731 str(construction_data)) 00732 00733 Triangle.__init__(self, 00734 ((vertices_names[0], 00735 vertices_names[1], 00736 vertices_names[2] 00737 ), 00738 {'side0' : leg0_length, 00739 'angle1' : 90, 00740 'side1' : leg1_length 00741 } 00742 ), 00743 rotate_around_isobarycenter=rotation 00744 ) 00745 00746 else: 00747 # copy of a given RightTriangle 00748 self._vertices = [arg.vertex0.clone(), 00749 arg.vertex1.clone(), 00750 arg.vertex2.clone() 00751 ] 00752 self._rotation_angle = arg.rotation_angle 00753 self._sides = [arg.side0.clone(), 00754 arg.side1.clone(), 00755 arg.side2.clone() 00756 ] 00757 self._angles = [arg.angle0.clone(), 00758 arg.angle1.clone(), 00759 arg.angle2.clone() 00760 ] 00761 # the other fields are re-created hereafter 00762 00763 self._name = self.vertex0.name + self.vertex1.name + self.vertex2.name 00764 00765 self.right_angle.set_mark("right") 00766 00767 random_number = "" 00768 for i in xrange(8): 00769 random_number += str(randomly.integer(0, 9)) 00770 00771 self._filename = _("RightTriangle") + "_" + self.name \ 00772 + "-" + random_number 00773 00774 00775 00776 00777 00778 00779 00780 # -------------------------------------------------------------------------- 00781 ## 00782 # @brief Returns leg0 (as a Segment) 00783 def get_leg0(self): 00784 return self._sides[0] 00785 # -------------------------------------------------------------------------- 00786 leg0 = property(get_leg0, 00787 doc = "First leg of the Triangle") 00788 00789 00790 00791 00792 00793 # -------------------------------------------------------------------------- 00794 ## 00795 # @brief Returns leg1 (as a Segment) 00796 def get_leg1(self): 00797 return self._sides[1] 00798 # -------------------------------------------------------------------------- 00799 leg1 = property(get_leg1, 00800 doc = "Second leg of the Triangle") 00801 00802 00803 00804 00805 00806 # -------------------------------------------------------------------------- 00807 ## 00808 # @brief Returns legs (as a Segment) 00809 def get_legs(self): 00810 return [self.leg0, self.leg1] 00811 # -------------------------------------------------------------------------- 00812 legs = property(get_legs, 00813 doc = "The two legs of the Right Triangle (in a list)") 00814 00815 00816 00817 00818 00819 # -------------------------------------------------------------------------- 00820 ## 00821 # @brief Returns hypotenuse (as a Segment) 00822 def get_hypotenuse(self): 00823 return self._sides[2] 00824 # -------------------------------------------------------------------------- 00825 hypotenuse = property(get_hypotenuse, 00826 doc = "Hypotenuse of the Right Triangle") 00827 00828 00829 00830 00831 00832 # -------------------------------------------------------------------------- 00833 ## 00834 # @brief Returns Tthe right angle (as an Angle) 00835 def get_right_angle(self): 00836 return self.angle1 00837 # -------------------------------------------------------------------------- 00838 right_angle = property(get_right_angle, 00839 doc = "Right Angle of the Right Triangle") 00840 00841 00842 00843 00844 00845 # -------------------------------------------------------------------------- 00846 ## 00847 # @brief Creates the correct pythagorean equality hyp²=leg0²+leg1² 00848 # @return an Equality but not usable to calculate (see substequality) 00849 def pythagorean_equality(self, **options): 00850 00851 objcts = [Item(('+', self.hypotenuse.length_name, 2)), 00852 Sum([Item(('+', self.leg0.length_name, 2)), 00853 Item(('+', self.leg1.length_name, 2))] 00854 )] 00855 00856 return Equality(objcts, **options) 00857 00858 00859 00860 00861 # -------------------------------------------------------------------------- 00862 ## 00863 # @brief Creates the correct (substitutable) pythagorean equality 00864 # @brief Uses the labels to determine the result... 00865 # @return a SubstitutableEquality 00866 def pythagorean_substequality(self, **options): 00867 # First, check the number of numeric data 00868 # and find the unknown side 00869 n_numeric_data = 0 00870 unknown_side = "" 00871 if self.leg0.label.is_numeric(): 00872 n_numeric_data += 1 00873 elif self.leg0.label.raw_value == "": 00874 unknown_side = 'leg0' 00875 if self.leg1.label.is_numeric(): 00876 n_numeric_data += 1 00877 elif self.leg1.label.raw_value == "": 00878 unknown_side = 'leg1' 00879 if self.hypotenuse.label.is_numeric(): 00880 n_numeric_data += 1 00881 elif self.hypotenuse.label.raw_value == "": 00882 unknown_side = 'hypotenuse' 00883 00884 if n_numeric_data != 2: 00885 raise error.ImpossibleAction("creation of a pythagorean equality "\ 00886 "when the number of known numeric " \ 00887 "values is different from 2.") 00888 00889 # Now create the SubstitutableEquality (so, also create the dictionnary) 00890 if unknown_side == 'leg0': 00891 subst_dict = {Value(self.leg1.length_name): self.leg1.label, 00892 Value(self.hypotenuse.length_name): \ 00893 self.hypotenuse.label 00894 } 00895 objcts = [Item(('+', self.leg0.length_name, 2)), 00896 Sum([Item(('+', self.hypotenuse.length_name, 2)), 00897 Item(('-', self.leg1.length_name, 2))] 00898 )] 00899 00900 elif unknown_side == 'leg1': 00901 subst_dict = {Value(self.leg0.length_name): self.leg0.label, 00902 Value(self.hypotenuse.length_name): \ 00903 self.hypotenuse.label 00904 } 00905 objcts = [Item(('+', self.leg1.length_name, 2)), 00906 Sum([Item(('+', self.hypotenuse.length_name, 2)), 00907 Item(('-', self.leg0.length_name, 2))] 00908 )] 00909 00910 elif unknown_side == 'hypotenuse': 00911 subst_dict = {Value(self.leg0.length_name): self.leg0.label, 00912 Value(self.leg1.length_name): self.leg1.label 00913 } 00914 objcts = [Item(('+', self.hypotenuse.length_name, 2)), 00915 Sum([Item(('+', self.leg0.length_name, 2)), 00916 Item(('+', self.leg1.length_name, 2))] 00917 )] 00918 00919 else: 00920 raise error.ImpossibleAction("creation of a pythagorean equality "\ 00921 "because no unknown side was found") 00922 00923 00924 return SubstitutableEquality(objcts, subst_dict) 00925 00926