-
-
Notifications
You must be signed in to change notification settings - Fork 237
/
TieManager.scala
95 lines (75 loc) · 3.13 KB
/
TieManager.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// (C) Uri Wilensky. https://github.com/NetLogo/NetLogo
package org.nlogo.agent
import
scala.util.control.Exception.ignoring
import
org.nlogo.api.{ AgentException, Numbers },
Numbers.Infinitesimal
class TieManager(links: TreeAgentSet, linkManager: LinkManager, protractor: Protractor) {
private var tieCount = 0
def hasTies: Boolean = tieCount > 0
def reset(): Unit = {
tieCount = 0
}
def setTieMode(link: Link, mode: String): Unit = {
if (link.isTied && mode == Link.MODE_NONE) {
tieCount -= 1
} else if (mode != Link.MODE_NONE) {
tieCount += 1
}
}
protected def tiedTurtles(root: Turtle, seenTurtles: Set[Turtle]): Seq[Turtle] = {
val tiedTurtles = linkManager.outLinks(root, links).collect {
case link if link.isTied => link.otherEnd(root)
}
tiedTurtles.filterNot(t => t.id == -1 || seenTurtles(t)).toSeq.distinct
}
private[agent] def turtleMoved(root: Turtle, newX: Double, newY: Double, oldX: Double, oldY: Double): Unit =
turtleMoved(root, newX, newY, oldX, oldY, Set(root))
private[agent] def turtleMoved(root: Turtle, newX: Double, newY: Double, oldX: Double, oldY: Double, seenTurtles: Set[Turtle]): Unit = {
val turtles = tiedTurtles(root, seenTurtles)
val allSeenTurtles = seenTurtles ++ turtles
turtles foreach {
t =>
val dx = newX - oldX
val dy = newY - oldY
ignoring(classOf[AgentException]) {
t.xandycor(t.xcor + dx, t.ycor + dy, allSeenTurtles, false)
}
}
}
private[agent] def turtleTurned(root: Turtle, newHeading: Double, oldHeading: Double): Unit =
turtleTurned(root, newHeading, oldHeading, Set(root))
private[agent] def turtleTurned(root: Turtle, newHeading: Double, oldHeading: Double, seenTurtles: Set[Turtle]) {
val isLinkedFixedly = (t: Turtle) => linkManager.linksTo(root, t, links)
.find( _.mode == Link.MODE_FIXED)
.nonEmpty
val getCoords = (t: Turtle) => (t.xcor(), t.ycor())
val squash = (x: Double) => if (StrictMath.abs(x) < Infinitesimal) 0 else x
val squashedSin = StrictMath.toRadians _ andThen StrictMath.sin andThen squash
val squashedCos = StrictMath.toRadians _ andThen StrictMath.cos andThen squash
val dh = Turtle.subtractHeadings(newHeading, oldHeading)
val (x, y) = getCoords(root)
val turtles = tiedTurtles(root, seenTurtles)
val allSeenTurtles = seenTurtles ++ turtles
turtles foreach {
t =>
val wentBoom =
try {
val r = protractor.distance(root, t, true)
if (r != 0) {
val theta = protractor.towards(root, t, true) + dh
val newX2 = x + r * squashedSin(theta)
val newY2 = y + r * squashedCos(theta)
t.xandycor(newX2, newY2, allSeenTurtles, false)
}
false
}
catch {
case _: AgentException => true
}
if (isLinkedFixedly(t) && !wentBoom)
t.heading(t.heading + dh, allSeenTurtles)
}
}
}