In Files

Parent

LabelledShape

Author

Manuela Ruiz (mruiz@lcc.uma.es)

This class represents a LabelledShape, that is, a shape with any number of labels

Attributes

s[RW]

Hash of lists of ListNodes, for the colinear segments There is one list for each present layer, mapped by the layer name

p[RW]

Hash of list of ListNodes, for the labelled points There is one list for each present layer, mapped by the layer name

Public Class Methods

new(edges, points_and_materials) click to toggle source
edges

list of edges

points_and_materials

list of pairs (point, material)

Initializes the hashes of maximal lines and labelled points, associated with layer 0

     # File lib/geometry.rb, line 611
611:         def initialize(edges, points_and_materials)

612:                 if !@s

613:                         @s = Hash.new(nil)

614:                         if Shade.using_sketchup

615:                                 Sketchup.active_model.layers.each { |layer|

616:                                         @s[layer.name] = LinearLinkedList.new

617:                                 }

618:                         else

619:                                 @s["Layer0"] = LinearLinkedList.new

620:                         end

621:                 end

622:                 if !@p

623:                         @p = Hash.new(nil)

624:                         if Shade.using_sketchup

625:                                 Sketchup.active_model.layers.each { |layer|

626:                                         @p[layer.name] = LinearLinkedList.new

627:                                 }

628:                         else

629:                                 @p["Layer0"] = LinearLinkedList.new

630:                         end

631:                 end

632:                 edges.each { |e|

633:                         segment = Segment.new(OrderedPoint.new(e.start.position), OrderedPoint.new(e.end.position))

634:                         segment_list = LinearLinkedList.new

635: 

636:                         if @s["Layer0"].kind_of? LinearLinkedList

637:                                 node = LinearLinkedListNode.new(segment.line_descriptor, segment_list, nil)

638:                         else

639:                                 node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, segment.line_descriptor, segment_list)

640:                         end

641:                         

642:                         inserted_node = @s["Layer0"].insert_node(node) #Insert the node corresponding to the line descriptor of the segment

643: 

644:                         #We create an auxiliar list filled with the new segment to add, in order to make the union and obtain the maximal lines

645:                         new_segment_list = LinearLinkedList.new

646:                         segment_node = LinearLinkedListNode.new(segment.clone, nil, nil)

647:                         new_segment_list.insert_node(segment_node)

648:                         

649:                         op_rel(inserted_node.list,  new_segment_list, Constants::UNION, Constants::SEGMENTS)

650:                 }

651:                 

652:                 #Compound the label lists

653:                 points_and_materials.each { |pair|

654:                         point = OrderedPoint.new(pair[0])

655:                         label = Label.new(pair[1])

656:                         point_list = LinearLinkedList.new

657:                         

658:                         if @p["Layer0"].kind_of? LinearLinkedList

659:                                 node = LinearLinkedListNode.new(label, point_list, nil)

660:                         else

661:                                 node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, label, point_list)

662:                         end

663:                         

664:                         inserted_node = @p["Layer0"].insert_node(node) #Insert the node corresponding to the label of the point

665:                         

666:                         point_node = LinearLinkedListNode.new(point, nil, nil)

667:                         inserted_node.list.insert_node(point_node) #Insert the point node

668:                 }             

669:                 recompute_intersection_points

670:         end

Public Instance Methods

add_label(point, value, layer_name) click to toggle source
point

a Point object

value

the name of the label value

layer_name

the name of the layer on which the label is going to be added

Adds a label to the shape in the position determined by point, with the specified value and in the specified layer

     # File lib/geometry.rb, line 731
731:         def add_label(point, value, layer_name)

732:                 if @p[layer_name]

733:                         label = Label.new(value)

734:                         point_list = LinearLinkedList.new

735:                         

736:                         node = LinearLinkedListNode.new(label, point_list, nil)

737:                         

738:                         inserted_node = @p[layer_name].insert_node(node) #Insert the node corresponding to the label of the point

739:                         

740:                         point_node = LinearLinkedListNode.new(OrderedPoint.new(point), nil, nil)

741:                         inserted_node.list.insert_node(point_node) #Insert the point node

742:                 end

743:         end
hash() click to toggle source
returns

the hash code for this labelled shape

      # File lib/geometry.rb, line 1581
1581:         def hash

1582:                 return [@s["Layer0"].hash, @p["Layer0"].hash].hash

1583:         end
load(path) click to toggle source
path

path to load the shape from

Loads the shape in the specified path

      # File lib/geometry.rb, line 1326
1326:         def load(path)

1327:     

1328:                 if Shade.using_sketchup

1329:                         extension = ShadeUtils.get_extension(path)

1330: 

1331:                         if extension == "skp"

1332: 

1333:                                 #We remove everything

1334:                                 rules = Shade.project.execution.grammar.rules

1335:                                 rules.each {|rule|

1336:                                         rule.erase

1337:                                 }

1338:                                 Shade.project.execution.current_shape.erase

1339:                                 Sketchup.active_model.active_entities.erase_entities(Sketchup.active_model.active_entities.to_a) 

1340: 

1341:                                 path = path.tr("\\","/") 

1342:                                 Sketchup.active_model.save("trash.skp")

1343:                                 Sketchup.open_file(path) #A group is loaded

1344:                                 File.delete("trash.skp")

1345:                                 entities = Sketchup.active_model.entities[0].entities

1346: 

1347:                                 edges = Array.new

1348:                                 points_and_materials = Array.new

1349: 

1350:                                 entities.each { |e|

1351:                                         if e.kind_of? Sketchup::Edge

1352:                                                 edges.push e

1353:                                         elsif e.kind_of? Sketchup::Group

1354:                                                 e.entities.each { |ge| 

1355:                                                         if ge.kind_of? Sketchup::ConstructionPoint

1356:                                                                 points_and_materials.push [ge.position, e.material]

1357:                                                         end

1358:                                                 }

1359: 

1360:                                         end

1361:                                 }

1362: 

1363:                                 self.refresh_from_info(edges, points_and_materials)

1364: 

1365:                                 Sketchup.active_model.active_entities.erase_entities(Sketchup.active_model.active_entities.to_a) 

1366: 

1367:                                 #We repaint everything

1368:                                 ShadeUtils.prepare_canvas(false)

1369:                                 rules.each {|rule|

1370:                                         rule.repaint

1371:                                 }

1372:                                 Shade.project.execution.current_shape.paint

1373:                         elsif extension == "txt"

1374:                                 File.open(path, 'r') do |f|

1375:                                         layer_found = false

1376:                                         while line = f.gets

1377:                                                 line_a1 = line.split(":")

1378:                                                 if line_a1[0].strip == "S" #Segment

1379:                                                         if !layer_found

1380:                                                                 if self.kind_of? CurrentLabelledShape

1381:                                                                         @s["Layer0"] = BalancedBinaryTree.new

1382:                                                                 else

1383:                                                                         @s["Layer0"] = LinearLinkedList.new

1384:                                                                 end

1385:                                                                 @p["Layer0"] = LinearLinkedList.new

1386:                                                                 layer_name = "Layer0"

1387:                                                                 layer_found = true

1388:                                                         end

1389:                                                         line_a = line_a1[1].split

1390:                                                         segment = Segment.new(OrderedPoint.new(Geom::Point3d.new(line_a[0].to_f.m, line_a[1].to_f.m, 0)), OrderedPoint.new(Geom::Point3d.new(line_a[2].to_f.m, line_a[3].to_f.m, 0)))

1391:                                                         segment_list = LinearLinkedList.new

1392: 

1393:                                                         if @s[layer_name].kind_of? LinearLinkedList

1394:                                                                 node = LinearLinkedListNode.new(segment.line_descriptor, segment_list, nil)

1395:                                                         else

1396:                                                                 node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, segment.line_descriptor, segment_list)

1397:                                                         end

1398: 

1399:                                                         inserted_node = @s[layer_name].insert_node(node) #Insert the node corresponding to the line descriptor of the segment

1400: 

1401:                                                         #We create an auxiliar list filled with the new segment to add, in order to make the union and obtain the maximal lines

1402:                                                         new_segment_list = LinearLinkedList.new

1403:                                                         segment_node = LinearLinkedListNode.new(segment.clone, nil, nil)

1404:                                                         new_segment_list.insert_node(segment_node)

1405: 

1406:                                                         op_rel(inserted_node.list,  new_segment_list, Constants::UNION, Constants::SEGMENTS)

1407: 

1408:                                                 elsif line_a1[0].strip == "L" #Label

1409:                                                         if !layer_found

1410:                                                                 if self.kind_of? CurrentLabelledShape

1411:                                                                         @s["Layer0"] = BalancedBinaryTree.new

1412:                                                                 else

1413:                                                                         @s["Layer0"] = LinearLinkedList.new

1414:                                                                 end

1415:                                                                 @p["Layer0"] = LinearLinkedList.new

1416:                                                                 layer_name = "Layer0"

1417:                                                                 layer_found = true

1418:                                                         end

1419:                                                         line_a = line_a1[1].split

1420:                                                         color = line_a[2]

1421:                                                         raise LoadError, "The color name: #{color} of shape in file #{path} is not recognized" unless Constants::RECOGNIZED_COLORS.include? color

1422: 

1423:                                                         label = Label.new(line_a[2])

1424:                                                         point = OrderedPoint.new(Geom::Point3d.new(line_a[0].to_f.m, line_a[1].to_f.m, 0))

1425:                                                         point_list = LinearLinkedList.new

1426: 

1427:                                                         if @p[layer_name].kind_of? LinearLinkedList

1428:                                                                 node = LinearLinkedListNode.new(label, point_list, nil)

1429:                                                         else

1430:                                                                 node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, label, point_list)

1431:                                                         end

1432: 

1433:                                                         inserted_node = @p[layer_name].insert_node(node) #Insert the node corresponding to the label of the point

1434:                                                         

1435:                                                         point_node = LinearLinkedListNode.new(point, nil, nil)

1436:                                                         inserted_node.list.insert_node(point_node) #Insert the point node

1437:                                                 elsif line_a1[0].strip == "LAYER" #Layer

1438:                                                         layer_name = line_a1[1].strip

1439:                                                         if self.kind_of? CurrentLabelledShape

1440:                                                                 @s[layer_name] = BalancedBinaryTree.new

1441:                                                         else

1442:                                                                 @s[layer_name] = LinearLinkedList.new

1443:                                                         end

1444:                                                         @p[layer_name] = LinearLinkedList.new

1445:                                                         layer_found = true

1446:                                                 end

1447:                                         end

1448:                                 end

1449:                                 recompute_intersection_points

1450:                                 #paint

1451:                         end

1452:                 else

1453:                         extension = ShadeUtils.get_extension(path)

1454:                 

1455:                         if extension == "txt"

1456:                                 layer_name = "Layer0"

1457:                                 File.open(path, 'r') do |f|

1458:                                         layer_found = false

1459:                                         while line = f.gets

1460:                                                 line_a1 = line.split(":")

1461:                                                 if line_a1[0].strip == "S" #Segment

1462:                                                         if !layer_found

1463:                                                                 if self.kind_of? CurrentLabelledShape

1464:                                                                         @s["Layer0"] = BalancedBinaryTree.new

1465:                                                                 else

1466:                                                                         @s["Layer0"] = LinearLinkedList.new

1467:                                                                 end

1468:                                                                 @p["Layer0"] = LinearLinkedList.new

1469:                                                                 layer_name = "Layer0"

1470:                                                                 layer_found = true

1471:                                                         end

1472:                                                         line_a = line_a1[1].split

1473:                                                         segment = Segment.new(OrderedPoint.new(Point.new(line_a[0].to_f, line_a[1].to_f, 0)), OrderedPoint.new(Point.new(line_a[2].to_f, line_a[3].to_f, 0)))

1474:                                                         segment_list = LinearLinkedList.new

1475: 

1476:                                                         if @s[layer_name].kind_of? LinearLinkedList

1477:                                                                 node = LinearLinkedListNode.new(segment.line_descriptor, segment_list, nil)

1478:                                                         else

1479:                                                                 node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, segment.line_descriptor, segment_list)

1480:                                                         end

1481: 

1482:                                                         inserted_node = @s[layer_name].insert_node(node) #Insert the node corresponding to the line descriptor of the segment

1483: 

1484:                                                         #We create an auxiliar list filled with the new segment to add, in order to make the union and obtain the maximal lines

1485:                                                         new_segment_list = LinearLinkedList.new

1486:                                                         segment_node = LinearLinkedListNode.new(segment.clone, nil, nil)

1487:                                                         new_segment_list.insert_node(segment_node)

1488: 

1489:                                                         op_rel(inserted_node.list,  new_segment_list, Constants::UNION, Constants::SEGMENTS)

1490: 

1491:                                                 elsif line_a1[0].strip == "L" #Label

1492:                                                         if !layer_found

1493:                                                                 if self.kind_of? CurrentLabelledShape

1494:                                                                         @s["Layer0"] = BalancedBinaryTree.new

1495:                                                                 else

1496:                                                                         @s["Layer0"] = LinearLinkedList.new

1497:                                                                 end

1498:                                                                 @p["Layer0"] = LinearLinkedList.new

1499:                                                                 layer_name = "Layer0"

1500:                                                                 layer_found = true

1501:                                                         end

1502:                                                         line_a = line_a1[1].split

1503:                                                         color = line_a[2]

1504:                                                         raise LoadError, "The color name: #{color} of shape in file #{path} is not recognized" unless Constants::RECOGNIZED_COLORS.include? color

1505:                                                         label = Label.new(line_a[2])

1506:                                                         point = OrderedPoint.new(Point.new(line_a[0].to_f, line_a[1].to_f, 0))

1507:                                                         point_list = LinearLinkedList.new

1508: 

1509:                                                         if @p[layer_name].kind_of? LinearLinkedList

1510:                                                                 node = LinearLinkedListNode.new(label, point_list, nil)

1511:                                                         else

1512:                                                                 node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, label, point_list)

1513:                                                         end

1514: 

1515:                                                         inserted_node = @p[layer_name].insert_node(node) #Insert the node corresponding to the label of the point

1516:                                                         

1517:                                                         point_node = LinearLinkedListNode.new(point, nil, nil)

1518:                                                         inserted_node.list.insert_node(point_node) #Insert the point node

1519:                                                 elsif line_a1[0].strip == "LAYER" #Layer

1520:                                                         layer_name = line_a1[1].strip

1521:                                                         if self.kind_of? CurrentLabelledShape

1522:                                                                 @s[layer_name] = BalancedBinaryTree.new

1523:                                                         else

1524:                                                                 @s[layer_name] = LinearLinkedList.new

1525:                                                         end

1526:                                                         @p[layer_name] = LinearLinkedList.new

1527:                                                         layer_found = true

1528:                                                 end

1529:                                         end

1530:                                 end

1531:                                 recompute_intersection_points

1532:                                 #paint

1533:                         end

1534:                 end

1535: 

1536:         end
op_rel(list1, list2, op_rel_type, c) click to toggle source

list1: a LinearLinkedList of Segments or Points list2: a LinearLinkedList of Segments or Points

op_rel_type

the operation or relation to perform. One of the following: Constants::UNION, Constants::INTERSECTION, Constants::DIFFERENCE,

Constants::SUBSHAPE, Constants::EQUAL

c

Constants::SEGMENT if segments are affected, Constants::POINTS if points are affected.

returns::true iff the specified relation (subshape or equal) holds (or false if it does not hold). In case it is an union or difference operation, it just overwrites list1 with the resulting list of the operation. In case it is an intersection, it returns a new segment list.

      # File lib/geometry.rb, line 952
 952:         def op_rel(list1, list2, op_rel_type, c)

 953:                 if (c == Constants::SEGMENTS)

 954:                         if (op_rel_type == Constants::UNION)

 955:                                 #Step 0

 956:                                 working_line_node = list2.first

 957:                                 linej_node = list1.first

 958:                                 if !list1.empty?

 959:                                         #Step 1

 960:                                         step1_union(list1, list2, working_line_node, linej_node)

 961:                                 else

 962:                                         #Step 8

 963:                                         #There may still be some unexamined lines in line2. Copy all the unexamined lines in line2 in their order, and attach them

 964:                                         #to the end of list list1

 965:                                         step8_union(list1, list2, working_line_node, linej_node)

 966:                                 end

 967:                         elsif (op_rel_type == Constants::DIFFERENCE)

 968:                                 #Step 0

 969:                                 if !list1.empty?

 970:                                         #step 1

 971:                                         working_line_node = list2.first

 972:                                         linej_node = list1.first

 973:                                         step1_difference(list1, list2, working_line_node, linej_node)

 974:                                 end

 975:                         elsif (op_rel_type == Constants::INTERSECTION)

 976:                                 if !list1.empty?

 977:                                         #Step 0

 978:                                         working_line_node = list2.first

 979:                                         linej_node = list1.first

 980:                                         list3 = LinearLinkedList.new

 981:                                         #step 1

 982:                                         step1_intersection(list1, list2, list3, working_line, linej)

 983:                                 end

 984:                         elsif (op_rel_type == Constants::SUBSHAPE)

 985:                                 #step 0

 986:                                 flag = true

 987:                                 if !list1.empty?

 988:                                         #step 1

 989:                                         working_line_node = list2.first

 990:                                         linej_node = list1.first

 991:                                         flag = step1_subshape(flag, list1, list2, working_line_node, linej_node)

 992:                                 else

 993:                                         flag = (list2.empty?)

 994:                                 end

 995:                         elsif (op_rel_type == Constants::EQUAL)

 996:                                 flag = (list1 == list2)

 997:                         end

 998:                 elsif (c == Constants::POINTS)

 999:                         if (op_rel_type == Constants::UNION)

1000:                                 list2.reset_iterator

1001:                                 while n = list2.get_next

1002:                                         point = n.key

1003:                                         list1.insert_node(LinearLinkedListNode.new(point.clone, nil, nil))

1004:                                 end

1005:                         elsif (op_rel_type == Constants::DIFFERENCE)

1006:                                 list2.reset_iterator

1007:                                 while n = list2.get_next

1008:                                         point = n.key

1009:                                         list1.delete_node(point)

1010:                                 end                         

1011:                         elsif (op_rel_type == Constants::INTERSECTION)

1012:                                 list3 = LinearLinkedList.new

1013:                                 list2.reset_iterator

1014:                                 while n = list2.get_next

1015:                                         point = n.key

1016:                                         if list1.get_node(point)

1017:                                                 list3.insert_node(LinearLinkedListNode.new(point.clone, nil, nil))

1018:                                         end

1019:                                 end

1020:                         elsif (op_rel_type == Constants::SUBSHAPE)

1021:                                 flag = true

1022:                                 list2.reset_iterator

1023:                                 while (flag && n = list2.get_next)

1024:                                         point = n.key

1025:                                         flag = list1.get_node(point)

1026:                                         if !flag

1027:                                                 flag = false

1028:                                         else

1029:                                                 flag = true

1030:                                         end

1031:                                 end

1032:                         elsif (op_rel_type == Constants::EQUAL)

1033:                                 flag = (list1 == list2)

1034:                         end

1035:                 end

1036:                 

1037:                 if (op_rel_type == Constants::INTERSECTION)

1038:                         return list3

1039:                 elsif (op_rel_type == Constants::SUBSHAPE) || (op_rel_type == Constants::EQUAL)

1040:                         return flag

1041:                 end

1042:         end
paint() click to toggle source

Paints the view of the shape

      # File lib/geometry.rb, line 1539
1539:         def paint()

1540:                 if Shade.using_sketchup

1541:                         entities = Sketchup.active_model.entities

1542:                         

1543:                         layers = Sketchup.active_model.layers

1544:                                         

1545:                         @s.each_key { |layer_name|

1546:                                 @s[layer.name].reset_iterator

1547:                                 while (node = @s[layer.name].get_next)

1548:                                         node.list.reset_iterator

1549:                                         while (segment_node = node.list.get_next)

1550:                                                 entities.add_edges segment_node.key.tail.point, segment_node.key.head.point

1551:                                         end

1552:                                 end

1553:                         }

1554:                                 

1555:                         @p.each_key { |layer_name|

1556:                                 @p[layer.name].reset_iterator

1557:                                 while (node = @p[layer.name].get_next)

1558:                                         label = node.key

1559:                                         node.list.reset_iterator

1560:                                         while (labelled_point_node = node.list.get_next)   

1561:                                                 if !(label.value==Constants::INTERSECTION_LABEL) #The label is a coloured circle

1562:                                                         label_group = entities.add_group

1563:                                                         

1564:                                                         # Add circle

1565:                                                         edges = label_group.entities.add_circle labelled_point_node.key.point, Constants::LABEL_VECTOR, Shade.label_radius

1566:                                                         #Add construction point in order to locate the center later

1567:                                                         label_group.entities.add_cpoint labelled_point_node.key.point

1568:                                                         #Add face

1569:                                                         face = label_group.entities.add_face edges                                       

1570:                                                         #Give color to the face

1571:                                                         label_group.material = label.value

1572:                                                 end

1573:                                         end

1574:                                 end

1575:                                 

1576:                         }

1577:                 end

1578:         end
recompute_intersection_points(testing = false) click to toggle source

Recompute the intersection points of the shape

     # File lib/geometry.rb, line 862
862:         def recompute_intersection_points(testing = false)

863:                 

864:                 @s.each_key { |layer_name|

865:                         #First, we remove the old intersection points, if any

866:                         @p[layer_name].delete_node(Label.new(Constants::INTERSECTION_LABEL))

867:             

868:                         s_array = @s[layer_name].to_array

869:             

870:                         #Second, we obtain the nodes of the maximal lines in order

871:                         @s[layer_name].reset_iterator

872:                         i = 0

873:                         while (node = @s[layer_name].get_next)

874:                                 j = i

875:                                 #Obtain next_node without breaking the iterator

876:                                 while (j < s_array.size)

877:                                         #puts "Comparing #{i} line with #{j} line"

878:                                         next_node = s_array[j]

879:                                         if !(next_node.key.sine == node.key.sine) #If line descriptors are not parallel...

880:                                                 current_segment_node = node.list.first

881:                                                 found1 = false

882:                                                 #While there are segments in node and the intersection is not found

883:                                                 while (current_segment_node && !found1)

884:                                                         current_segment = current_segment_node.key

885:                                                         segment_node = next_node.list.first

886:                                                         found2 = false

887:                                                         #While there are segments in next_node and the intersection is not found

888:                                                         while (segment_node && !found1 && !found2)

889:                                                                 segment = segment_node.key

890:                                                                 #Calculate ua

891:                                                                 #Numerator

892:                                                                 uan = (((segment.head.x - segment.tail.x)*(current_segment.tail.y - segment.tail.y)) - ((segment.head.y - segment.tail.y)*(current_segment.tail.x - segment.tail.x)))

893:                                                                 #Denominator

894:                                                                 uad = (((segment.head.y - segment.tail.y)*(current_segment.head.x - current_segment.tail.x)) - ((segment.head.x - segment.tail.x)*(current_segment.head.y - current_segment.tail.y)))

895:                                                                 #The denominator is not going to be zero since the studied lines are not parallel neither coincident

896:                                                                 ua = uan/uad

897:                                                                 

898:                                                                 #Calculate ub

899:                                                                 #Numerator

900:                                                                 ubn = (((current_segment.head.x - current_segment.tail.x)*(current_segment.tail.y - segment.tail.y)) - ((current_segment.head.y - current_segment.tail.y)*(current_segment.tail.x - segment.tail.x)))

901:                                                                 #Denominator

902:                                                                 ubd = uad

903:                                                                 #The denominator is not going to be zero since the studied lines are not parallel neither coincident

904:                                                                 ub = ubn/ubd

905:                                                                 #if testing

906:                                                                         #puts "ua: #{ua}, ub: #{ub}"

907:                                                                 #end

908:                                                                 if (ua > (1 + Constants::EPSILON)) #The current_segment does not intersect with the next_node line descriptor. Maybe some higher segment does intersect

909:                                                                         found2 = true

910:                                                                 elsif (ua < (0 - Constants::EPSILON))

911:                                                                         found1 = true #We can stop searching this pair of lines, since there is not any pair of segments that intersect

912:                                                                 elsif ((((0 - Constants::EPSILON) <= ub) && (ub <= (1 + Constants::EPSILON))) && (((0 - Constants::EPSILON) <= ua) && (ua <= (1 + Constants::EPSILON)))) #We have found the intersection

913:                                                                         found1 = true #We can stop searching this pair of lines

914:                                                                         label = Label.new(Constants::INTERSECTION_LABEL)

915:                                                                         point_list = LinearLinkedList.new

916:                                                                         if @p[layer_name].kind_of? LinearLinkedList

917:                                                                                 label_node = LinearLinkedListNode.new(label, point_list, nil)

918:                                                                         else

919:                                                                                 label_node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, label, point_list)

920:                                                                         end

921:                                                                         

922:                                                                         inserted_node = @p[layer_name].insert_node(label_node) #Insert the node corresponding to the label of the point

923:                                                                 

924:                                                                         #Calculate the point

925:                                                                         x = current_segment.tail.x + (ua * (current_segment.head.x - current_segment.tail.x))

926:                                                                         y = current_segment.tail.y + (ua * (current_segment.head.y - current_segment.tail.y))

927:                                                                         point = Point.new(x,y,0)

928:                                                                         point_node = LinearLinkedListNode.new(OrderedPoint.new(point), nil, nil)

929:                                                                         inserted_node.list.insert_node(point_node) #Insert the point node

930:                                                                         #puts "point inserted: #{point.x}, #{point.y}"

931:                                                                 end

932:                                                                 segment_node = segment_node._next

933:                                                         end

934:                                                         current_segment_node = current_segment_node._next

935:                                                 end

936:                                         end

937:                                         j+=1

938:                                 end

939:                                 i+=1

940:                         end

941:                 }

942:         end
refresh_from_info(edges, points_and_materials, layer) click to toggle source
edges

an array of SketchUp Edges

points_and_materials

an array of pairs [Point3d, Material], both of them are classes of SketchUp

layer

name of the layer that is affected

Refresh the internal representation of the shape according to the current SketchUp canvas content inside the group of the shape

     # File lib/geometry.rb, line 677
677:         def refresh_from_info(edges, points_and_materials, layer)

678:                 if (@s[layer] and @p[layer])

679:                         if @s[layer].kind_of? BalancedBinaryTree

680:                                 @s[layer] = BalancedBinaryTree.new

681:                         else

682:                                 @s[layer] = LinearLinkedList.new

683:                         end

684:                         @p[layer] = LinearLinkedList.new

685:                         edges.each { |e|

686:                                 segment = Segment.new(OrderedPoint.new(e.start.position), OrderedPoint.new(e.end.position))

687:                                 segment_list = LinearLinkedList.new

688: 

689:                                 if @s[layer].kind_of? LinearLinkedList

690:                                         node = LinearLinkedListNode.new(segment.line_descriptor, segment_list, nil)

691:                                 else

692:                                         node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, segment.line_descriptor, segment_list)

693:                                 end

694:                                 

695:                                 inserted_node = @s[layer].insert_node(node) #Insert the node corresponding to the line descriptor of the segment

696: 

697:                                 #We create an auxiliar list filled with the new segment to add, in order to make the union and obtain the maximal lines

698:                                 new_segment_list = LinearLinkedList.new

699:                                 segment_node = LinearLinkedListNode.new(segment.clone, nil, nil)

700:                                 new_segment_list.insert_node(segment_node)

701:                                 

702:                                 op_rel(inserted_node.list,  new_segment_list, Constants::UNION, Constants::SEGMENTS)

703:                         }

704:                         

705:                         #Compound the label lists

706:                         points_and_materials.each { |pair|

707:                                 point = OrderedPoint.new(pair[0])

708:                                 label = Label.new(pair[1])

709:                                 point_list = LinearLinkedList.new

710:                                 

711:                                 if @p[layer].kind_of? LinearLinkedList

712:                                         node = LinearLinkedListNode.new(label, point_list, nil)

713:                                 else

714:                                         node = BalancedBinaryTreeNode.new(Constants::BALANCED, nil, nil, label, point_list)

715:                                 end

716:                                 

717:                                 inserted_node = @p[layer].insert_node(node) #Insert the node corresponding to the label of the point

718:                                 

719:                                 point_node = LinearLinkedListNode.new(point, nil, nil)

720:                                 inserted_node.list.insert_node(point_node) #Insert the point node

721:                         }            

722:                         recompute_intersection_points

723:                 end

724:         end
save(path) click to toggle source
path

path to save the shape in

Saves the shape in the specified path

      # File lib/geometry.rb, line 1246
1246:         def save(path)

1247:     

1248:                 if Shade.using_sketchup

1249:                         extension = ShadeUtils.get_extension(path)

1250: 

1251:                         if extension == "skp"

1252:                                 rules = Shade.project.execution.grammar.rules

1253:                                 rules.each {|rule|

1254:                                         rule.erase

1255:                                 }

1256:                                 Sketchup.active_model.entities

1257:                                 Shade.project.execution.current_shape.erase

1258: 

1259:                                 Sketchup.active_model.active_entities.erase_entities(Sketchup.active_model.active_entities.to_a) 

1260: 

1261:                                 self.paint

1262: 

1263:                                 path = path.tr("\\","/") 

1264:                                 Sketchup.active_model.save(path)

1265: 

1266:                                 ShadeUtils.prepare_canvas(false)

1267:                                 rules.each {|rule|

1268:                                         rule.repaint

1269:                                 }

1270:                                 Shade.project.execution.current_shape.paint

1271:                         elsif extension == "txt"

1272:                                 File.open(path, 'w') do |f|

1273:                                         Sketchup.active_model.layers.each { |layer|

1274:                                                 f.write("LAYER: #{layer.name}\n")

1275:                                                 @s[layer.name].reset_iterator

1276:                                                 while s_node = @s[layer.name].get_next

1277:                                                         s_node.list.reset_iterator

1278:                                                         while s = s_node.list.get_next

1279:                                                                 f.write("S: #{s.key.tail.x.to_f.to_m} #{s.key.tail.y.to_f.to_m} #{s.key.head.x.to_f.to_m} #{s.key.head.y.to_f.to_m}\n")

1280:                                                         end

1281:                                                 end

1282:                                                 @p[layer.name].reset_iterator

1283:                                                 while l_node = @p[layer.name].get_next

1284:                                                         if !(l_node.key.value == Constants::INTERSECTION_LABEL)

1285:                                                                 l_node.list.reset_iterator

1286:                                                                 while l = l_node.list.get_next

1287:                                                                         f.write("L: #{l.key.x.to_f.to_m} #{l.key.y.to_f.to_m} #{l_node.key.value}\n")

1288:                                                                 end

1289:                                                         end

1290:                                                 end

1291:                                         }

1292:                                 end

1293:                         end

1294:                 else

1295:                         extension = ShadeUtils.get_extension(path)

1296:                         if extension == "txt"

1297:                                 File.open(path, 'w') do |f|

1298:                                         @s.each_key { |layer_name|

1299:                                                 f.write("LAYER: #{layer_name}\n")

1300:                                                 @s[layer_name].reset_iterator

1301:                                                 while s_node = @s[layer_name].get_next

1302:                                                         s_node.list.reset_iterator

1303:                                                         while s = s_node.list.get_next

1304:                                                                 f.write("S: #{s.key.tail.x.to_f} #{s.key.tail.y.to_f} #{s.key.head.x.to_f} #{s.key.head.y.to_f}\n")

1305:                                                         end

1306:                                                 end

1307:                                                 @p[layer_name].reset_iterator

1308:                                                 while l_node = @p[layer_name].get_next

1309:                                                         if !(l_node.key.value == Constants::INTERSECTION_LABEL)

1310:                                                                 l_node.list.reset_iterator

1311:                                                                 while l = l_node.list.get_next

1312:                                                                         f.write("L: #{l.key.x.to_f} #{l.key.y.to_f} #{l_node.key.value}\n")

1313:                                                                 end

1314:                                                         end

1315:                                                 end

1316:                                         }

1317:                                 end

1318:                         end

1319:                 end

1320: 

1321:         end
shape_expression(other_shape, op_rel_type, c, print = false) click to toggle source
other_shape

another LabelledShape

op_rel_type

the operation or relation to perform. One of the following: Constants::UNION, Constants::INTERSECTION, Constants::DIFFERENCE,

Constants::SUBSHAPE, Constants::EQUAL

c

Constants::SEGMENTS if segments are affected, Constants::POINTS if points are affected.

returns

true iff the specified relation (subshape or equal) holds (or false if it does not hold). In case it is an operation,

it just overwrites this shape with the resulting shape of the operation OR returns another shape in case it is an intersection

     # File lib/geometry.rb, line 752
752:         def shape_expression(other_shape, op_rel_type, c, print = false)

753: 

754:                 global_flag = true

755:                 

756:                 result = LabelledShape.new(Array.new, Array.new)

757:                 if (c == Constants::SEGMENTS)

758:                         c1_hash = @s

759:                         c2_hash = other_shape.s

760:                         c3_hash = result.s

761:                 elsif (c==Constants::POINTS)

762:                         c1_hash = @p

763:                         c2_hash = other_shape.p  

764:                         c3_hash = result.p

765:                 end

766: 

767:                 c2_hash.each_key { |layer_name|

768:                 

769:                         flag = true

770:                         #Initialization

771:                         

772:                         c1 = c1_hash[layer_name]

773:                         c2 = c2_hash[layer_name]

774:                         c3 = c3_hash[layer_name]

775:                         

776:                         #NOTE: if c2 is empty, then the subshape relation DOES hold

777:                         

778:                         if (!c1) 

779:                                 if (c == Constants::SEGMENTS)

780:                                         if self.kind_of? CurrentLabelledShape

781:                                                 c1 = BalancedBinaryTree.new

782:                                                 c1_hash[layer_name] = c1

783:                                         else

784:                                                 c1 = LinearLinkedList.new

785:                                                 c1_hash[layer_name] = c1

786:                                         end

787:                                 else

788:                                         c1 = LinearLinkedList.new

789:                                         c1_hash[layer_name] = c1

790:                                 end

791:                         end

792:                         if (!c2) 

793:                                 if (c == Constants::SEGMENTS)

794:                                         if self.kind_of? CurrentLabelledShape

795:                                                 c2 = BalancedBinaryTree.new

796:                                                 c2_hash[layer_name] = c2

797:                                         else

798:                                                 c2 = LinearLinkedList.new

799:                                                 c2_hash[layer_name] = c2

800:                                         end

801:                                 else

802:                                         c2 = LinearLinkedList.new

803:                                         c2_hash[layer_name] = c2

804:                                 end

805:                         end

806:                         c2.reset_iterator

807:                         while ((v = c2.get_next) && flag)

808:                                 if (!(v.key == Label.new(Constants::INTERSECTION_LABEL))) #we do not need to compare intersection points

809:                                         u = c1.get_node(v.key)

810:                                         if u #Matching keys found. Perform the appropiate action

811:                                                 if (op_rel_type == Constants::UNION) || (op_rel_type == Constants::INTERSECTION) || (op_rel_type == Constants::DIFFERENCE)

812:                                                         if (op_rel_type == Constants::UNION) || (op_rel_type == Constants::DIFFERENCE)

813:                                                                 op_rel(u.list, v.list, op_rel_type, c)

814:                                                         else

815:                                                                 result_list = op_rel(u.list, v.list, op_rel_type, c)

816:                                                                 node = LinearLinkedListNode.new(v.key.clone, result_list, nil)

817:                                                                 c3.insert_node node

818:                                                         end

819:                                                         if u.list.empty?

820:                                                                 c1.delete_node(u.key) 

821:                                                                 flag =  !c1.empty? #CHECK: es esto equivalente al alg. de krishnamurti??

822:                                                         end

823:                                                 elsif (op_rel_type == Constants::SUBSHAPE) || (op_rel_type == Constants::EQUAL)

824:                                                         flag = op_rel(u.list, v.list, op_rel_type, c)

825:                                                 end

826:                                         else #There is no node with the same key value as v

827:                                                 if op_rel_type == Constants::UNION

828:                                                         if c1.kind_of? BalancedBinaryTree

829:                                                                 new_node = BalancedBinaryTreeNode.new(0,nil,nil,v.key.clone, v.list.clone)

830:                                                         else

831:                                                                 new_node = LinearLinkedListNode.new(v.key.clone, v.list.clone, nil)

832:                                                         end

833:                                                         c1.insert_node(new_node)                                 

834:                                                 elsif (op_rel_type == Constants::SUBSHAPE) || (op_rel_type == Constants::EQUAL)

835:                                                         flag = false

836:                                                 end

837:                                         end

838:                                 end

839:                         end

840:                         

841:                         if (c == Constants::SEGMENTS)

842:                                 #puts "#{layer_name}: #{flag}"

843:                         end

844: 

845:                         global_flag = (global_flag and flag)

846:                 }

847:                 

848:                 #Finishing touches

849:                 if ((op_rel_type == Constants::SUBSHAPE) || (op_rel_type == Constants::EQUAL))

850:                         return global_flag

851:                 elsif (op_rel_type == Constants::INTERSECTION)

852:                         if (c == Constants::SEGMENTS)

853:                                 result.recompute_intersection_points

854:                         end

855:                         return result

856:                 elsif (c == Constants::SEGMENTS)

857:                         self.recompute_intersection_points

858:                 end

859:         end
step1_difference(list1, list2, working_line_node, linej_node) click to toggle source

First step of the difference algorithm of Krishnamurti

      # File lib/geometry.rb, line 1111
1111:         def step1_difference(list1, list2, working_line_node, linej_node)

1112:                 if (linej_node.key.tail < working_line_node.key.head)

1113:                         #step 3

1114:                         if (working_line_node.key.tail < linej_node.key.head)

1115:                                 #step 5

1116:                                 lineA = Segment.new(linej_node.key.tail, working_line_node.key.tail)

1117:                                 lineB = Segment.new(working_line_node.key.head, linej_node.key.head)

1118:                                 if (linej_node.key.tail < working_line_node.key.tail) && (linej_node.key.head <= working_line_node.key.head)

1119:                                         linej_node.key = lineA.clone

1120:                                         step4_difference(list1, list2, working_line_node, linej_node)

1121:                                 elsif (working_line_node.key.tail <= linej_node.key.tail) && (working_line_node.key.head < linej_node.key.head)

1122:                                         linej_node.key = lineB.clone

1123:                                         step2_difference(list1, list2, working_line_node, linej_node)

1124:                                 elsif (linej_node.key.tail < working_line_node.key.tail) && (working_line_node.key.head < linej_node.key.head)

1125:                                         linej_node.key = lineB.clone

1126:                                         list1.insert_node(LinearLinkedListNode.new(lineA.clone, nil, nil))

1127:                                         step2_difference(list1, list2, working_line_node, linej_node)

1128:                                 elsif (working_line_node.key.tail <= linej_node.key.tail) && (linej_node.key.head <= working_line_node.key.head)

1129:                                         list1.delete_node(linej_node.key)

1130:                                         step4_difference(list1, list2, working_line_node, linej_node)

1131:                                 end

1132:                         else

1133:                                 #step 4

1134:                                 step4_difference(list1, list2, working_line_node, linej_node)

1135:                         end

1136:                 else

1137:                         #step 2

1138:                         step2_difference(list1, list2, working_line_node, linej_node)

1139:                 end

1140:         end
step1_intersection(list1, list2, list3, working_line_node, linej_node) click to toggle source

First step of the intersection algorithm of Krishnamurti

      # File lib/geometry.rb, line 1163
1163:         def step1_intersection(list1, list2, list3, working_line_node, linej_node)

1164:                 if (linej_node.key.tail < working_line_node.key.head)

1165:                         #step 3

1166:                         if (working_line_node.key.tail < linej_node.key.head)

1167:                                 #step 5

1168:                                 #step 5.1

1169:                                 if (linej_node.key.tail < working_line_node.key.tail)

1170:                                         new_tail = working_line_node.key.tail

1171:                                 else

1172:                                         new_tail = linej_node.key.tail

1173:                                 end

1174:                                 if (working_line_node.key.head < linej_node.key.head) || (linej_node.key.head == working_line_node.key.head)

1175:                                         #step 5.2

1176:                                         new_head = working_line_node.key.head

1177:                                         segmentk = Segment.new(new_tail, new_head)

1178:                                         list3.insert_node(LinearLinkedListNode.new(segmentk, nil, nil))

1179:                                         step2_intersection(list1, list2, list3, working_line_node, linej_node)

1180:                                 else

1181:                                         #step 5.3

1182:                                         new_head = linej_node.key.head

1183:                                         segmentk = Segment.new(new_tail, new_head)

1184:                                         list3.insert_node(LinearLinkedListNode.new(segmentk, nil, nil))

1185:                                         step4_intersection(list1, list2, list3, working_line_node, linej_node)

1186:                                 end

1187:                         else

1188:                                 #step 4

1189:                                 step4_intersection(list1, list2, list3, working_line_node, linej_node)

1190:                         end

1191:                 else

1192:                         #step 2

1193:                         step2_intersection(list1, list2, list3, working_line_node, linej_node)

1194:                 end

1195:         end
step1_subshape(flag, list1, list2, working_line_node, linej_node) click to toggle source

First step of the subshape algorithm of Krishnamurti

      # File lib/geometry.rb, line 1214
1214:         def step1_subshape(flag, list1, list2, working_line_node, linej_node)

1215:                 if (working_line_node.key.tail < linej_node.key.head)

1216:                         #step3

1217:                         if (linej_node.key.tail < working_line_node.key.head)

1218:                                 #step4

1219:                                 if ((working_line_node.key.tail >= linej_node.key.tail) && (working_line_node.key.head <= linej_node.key.head))

1220:                                         #step 5

1221:                                         if (working_line_node._next)

1222:                                                 working_line_node = working_line_node._next

1223:                                                 flag = step1_subshape(flag, list1, list2, working_line_node, linej_node)

1224:                                         end

1225:                                 else

1226:                                         flag = false

1227:                                 end

1228:                         else

1229:                                 flag = false

1230:                         end

1231:                 else

1232:                         #step2

1233:                         if (linej_node._next)

1234:                                 linej_node = linej_node._next

1235:                                 flag = step1_subshape(flag, list1, list2, working_line_node, linej_node)

1236:                         else

1237:                                 flag = false

1238:                         end

1239:                 end

1240:                 return flag

1241:         end
step1_union(list1, list2, working_line_node, linej_node) click to toggle source

First step of the union algorithm of Krishnamurti

      # File lib/geometry.rb, line 1045
1045:         def step1_union(list1, list2, working_line_node, linej_node)

1046:                 if (linej_node.key.tail <= working_line_node.key.head) 

1047:                         #Step 3

1048:                         if (working_line_node.key.tail <= linej_node.key.head)

1049:                                 #Step 5

1050:                                 if (working_line_node.key.tail < linej_node.key.tail)

1051:                                         linej_node.key.tail = working_line_node.key.tail.clone

1052:                                 else

1053:                                         working_line_node.key.tail = linej_node.key.tail.clone

1054:                                 end

1055:                                 #Step 6

1056:                                 if (linej_node.key.head >= working_line_node.key.head) 

1057:                                         #GOTO step 2

1058:                                         step2_union(list1, list2, working_line_node, linej_node)

1059:                                 else

1060:                                         list1.delete_node(linej_node.key)

1061:                                         #Step 4

1062:                                         step4_union(list1, list2, working_line_node, linej_node)

1063:                                 end

1064:                                 

1065:                         else

1066:                                 #Step 4

1067:                                 step4_union(list1, list2, working_line_node, linej_node)

1068:                         end

1069:                 else #the working line shares no common line with any line line(k>1) in list1, and working_line < linej

1070:                         #insert working_line into list1 as the maximal line immediately preceding linej in the list

1071:                         list1.insert_node(LinearLinkedListNode.new(working_line_node.key.clone, nil, nil))

1072:                         #Step 2

1073:                         step2_union(list1, list2, working_line_node, linej_node)

1074:                 end

1075:         end
step2_difference(list1, list2, working_line_node, linej_node) click to toggle source

Second step of the difference algorithm of Krishnamurti

      # File lib/geometry.rb, line 1143
1143:         def step2_difference(list1, list2, working_line_node, linej_node)

1144:                 if (working_line_node._next)

1145:                         working_line_node = working_line_node._next

1146:                         step1_difference(list1, list2, working_line_node, linej_node)

1147:                 else

1148:                         return

1149:                 end

1150:         end
step2_intersection(list1, list2, list3, working_line_node, linej_node) click to toggle source

Second step of the intersection algorithm of Krishnamurti

      # File lib/geometry.rb, line 1198
1198:         def step2_intersection(list1, list2, list3, working_line_node, linej_node)

1199:                 if (working_line_node._next)

1200:                         working_line_node = working_line_node._next

1201:                         step1_intersection(list1, list2, list3, working_line_node, linej_node)

1202:                 end

1203:         end
step2_union(list1, list2, working_line_node, linej_node) click to toggle source

Second step of the union algorithm of Krishnamurti

      # File lib/geometry.rb, line 1078
1078:         def step2_union(list1, list2, working_line_node, linej_node)

1079:                 if (working_line_node._next)

1080:                         working_line_node = working_line_node._next

1081:                         #GOTO step1

1082:                         step1_union(list1, list2, working_line_node, linej_node)

1083:                 else

1084:                         #Step 9

1085:                         return

1086:                 end

1087:         end
step4_difference(list1, list2, working_line_node, linej_node) click to toggle source

Fourth step of the difference algorithm of Krishnamurti

      # File lib/geometry.rb, line 1153
1153:         def step4_difference(list1, list2, working_line_node, linej_node)

1154:                 if (linej_node._next)

1155:                         linej_node = linej_node._next

1156:                         step1_difference(list1, list2, working_line_node, linej_node)

1157:                 else

1158:                         return

1159:                 end

1160:         end
step4_intersection(list1, list2, list3, working_line_node, linej_node) click to toggle source

Fourth step of the intersection algorithm of Krishnamurti

      # File lib/geometry.rb, line 1206
1206:         def step4_intersection(list1, list2, list3, working_line_node, linej_node)

1207:                 if (linej_node._next)

1208:                         linej_node = linej_node._next

1209:                         step1_intersection(list1, list2, list3, working_line, linej)

1210:                 end

1211:         end
step4_union(list1, list2, working_line_node, linej_node) click to toggle source

Fourth step of the union algorithm of Krishnamurti

      # File lib/geometry.rb, line 1090
1090:         def step4_union(list1, list2, working_line_node, linej_node)

1091:                 if (linej_node._next)

1092:                         linej_node = linej_node._next

1093:                         #GOTO step1

1094:                         step1_union(list1, list2, working_line_node, linej_node)

1095:                 else

1096:                         list1.insert_node(LinearLinkedListNode.new(working_line_node.key.clone, nil, nil))

1097:                         #GOTO Step 8

1098:                         step8_union(list1, list2, working_line_node, linej_node)

1099:                 end

1100:         end
step8_union(list1, list2, working_line_node, linej_node) click to toggle source

Eighth step of the union algorithm of Krishnamurti

      # File lib/geometry.rb, line 1103
1103:         def step8_union(list1, list2, working_line_node, linej_node)

1104:                 while (working_line_node)

1105:                         list1.insert_node(LinearLinkedListNode.new(working_line_node.key.clone, nil, nil))

1106:                         working_line_node = working_line_node._next

1107:                 end

1108:         end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.