[[http://www.siedler-games.de|{{:sg-link.jpg|}}]] ====== IsInSectorRange ====== **//Hinweis//:** Normalerweise reicht es völlig, wenn man die Funktion IsNear() verwendet! Diese Funktion hier macht nur in ganz speziellen Fällen Sinn und soll auch eigentlich nur das Prinzip der Entfernungsberechnung zwischen 2 Punkten verdeutlichen!\\ Mit Hilfe dieser kleinen Funktion kann man feststellen, ob ein bestimmter Punkt 2 innerhalb eines angegebenen Radius (Range) und in einem bestimmten Sektor (Viertel- oder Halbkreis) zu einem Punkt 1 liegt, und wie groß die Entfernung (gerade Linie) in Siedlerzentimetern zwischen den zwei Punkten ist. Die Funktion liefert vier Werte zurück: - Boolscher Wert (true/false) für Punkt 2 liegt innerhalb des Radius **und** des Sektors (wenn angegeben) oder nicht - Distanz zwischen Punkt 1 und 2 (in Siedlerzentimetern) - Winkel in Grad (Ganzzahl zwischen 0 und 360) zwischen Punkt 1 und Punkt 2 - Den Sektor in dem sich Punkt 2 befindet (Zahlenwert, Werte siehe Abb. unten)\\ Wenn der zurückgelieferte Sektorwert 0 ist, dann sind Punkt 1 und 2 identisch (gleiche Koordinaten). Wenn Punkt 2 genau auf einer der Achsen (X, Y) von Punkt 1 liegt, wird als Sektorenwert der jeweilige Zahlenwert für die Halbkreisangabe zurückgeliefert. Die beiden Punkte 1 und 2 können jeweils angegeben werden als * Entity Id = Zahl = 77399 * Entity Name (benannte (Script-)Entity) = String = "Punkt_1" * Positionstable = Table = {X = 12800, Y = 12800} Der Aufruf der Funktion erfolgt dann bspw. so: function xy() local isInRange, distance, angle, isInSector = IsPointInRange("Punkt_1",77399,1500,9) if isInRange then Message("Der Punkt liegt innerhalb des Radius in einer Entfernung von "..distance.." in Sektor "..isInSector.." in einem Winkel von "..angle.." Grad") else Message("Der Punkt liegt ausserhalb des Radius oder Sektors in einer Entfernung von "..distance) end end oder so (wenn die Sektorangabe weggelassen wird, oder gleich 0 ist, dann wird wie bei IsNear() der Vollkreis genommen): function xy() local isInRange, distance, angle, isInSector = IsPointInRange({X=6400,Y=12800},"Punkt_2",1500) if isInRange then Message("Der Punkt liegt innerhalb des Radius in einer Entfernung von "..distance.." in Sektor "..isInSector.." in einem Winkel von "..angle.." Grad") else Message("Der Punkt liegt ausserhalb des Radius in einer Entfernung von "..distance) end end oder so wenn man die Entfernung, den Winkel und den Sektor (zur Weiterverarbeitung) nicht braucht: function xy() if IsInSectorRange("Punkt_1",77399,1500,9) then Message("Der Punkt liegt innerhalb des Radius und Sektors") else Message("Der Punkt liegt ausserhalb des Radius oder Sektors") end end Aus der Abbildung kann man die entsprechenden Sektorenwerte für die Viertel-, bzw. Halbkreise entnehmen: {{utilfunctions:sektoren_01.png}}\\ //Anmerkung//: Die Werte für die Halbkreise ergeben sich aus der Addition der jeweiligen Viertelkreiswerte. ===== Code ===== irgendwo an eine freie Stelle (nicht innerhalb anderer Funktionen!) ins Script kopieren: function IsInSectorRange(_pos1,_pos2,_range,_sector) local pos = {_pos1,_pos2} local sector = _sector or 0 local sectorTemp = sector assert(type(_range) == "number", "Der Radius muss ein Zahlenwert sein") assert(type(sector) == "number", "Die Sektorangabe muss ein Zahlenwert sein") assert(sector >= 0 and sector <=12 and sector ~= 5 and sector ~= 7 and sector ~= 10 and sector ~= 11, "Der Sektorwert muss: 0, 1, 2, 3, 4, 6, 8, 9, oder 12 betragen") for i=1,2 do if type (pos[i]) == "string" or type (pos[i]) == "number" then pos[i] = GetPosition(GetEntityId(pos[i] )); end end if (sector == 3) then sector = 1 sectorTemp = 2 elseif (sector == 6) then sector = 2 sectorTemp = 4 elseif (sector == 9) then sector = 8 sectorTemp = 1 elseif (sector == 12) then sector = 4 sectorTemp = 8 end local a = 0 local angle = 0 local inSector = 0 local distance = 0 local inRange = false local diff_X = (pos[1].X - pos[2].X) local diff_Y = (pos[1].Y - pos[2].Y) if (diff_X == 0 or diff_Y == 0) then if ((diff_X == 0) and (diff_Y == 0)) then inSector = 0 distance = 0 angle = 0 elseif (diff_X == 0 and diff_Y > 0) then inSector = 9 distance = math.abs(diff_Y) angle = 90 elseif (diff_X == 0 and diff_Y < 0) then inSector = 6 distance = math.abs(diff_Y) angle = 270 elseif (diff_X > 0 and diff_Y == 0) then inSector = 3 distance = math.abs(diff_X) angle = 0 elseif (diff_X < 0 and diff_Y == 0) then inSector = 12 distance =math.abs(diff_X) angle = 180 end else if ((diff_X > 0) and (diff_Y > 0)) then inSector = 1 a = diff_Y elseif ((diff_X > 0) and (diff_Y < 0)) then inSector = 2 a = diff_X angle = 270 elseif ((diff_X < 0) and (diff_Y < 0)) then inSector = 4 a = math.abs(diff_Y) angle = 180 elseif ((diff_X < 0) and (diff_Y > 0)) then inSector = 8 a = math.abs(diff_X) angle = 90 end distance = math.sqrt((pos[1].X - pos[2].X)^2 + (pos[1].Y - pos[2].Y)^2) angle = angle + math.floor(math.deg(math.asin(a/distance)) + 0.5) end if distance <= _range then inRange = true end if (sector ~= 0 and inSector ~= 0 and inRange) then if (inSector ~= sector and inSector ~= sectorTemp) then inRange = false end end return inRange, distance, angle, inSector end ===== Entfernung/ Distanz ===== Wer einfach nur die Entfernung zwischen 2 Punkten (Entities) wissen will, der kommt hiermit aus: -- Hiermit kann man sich einfach nur die Enfernung von zwei Entities zurückgeben lassen function GetDistance(_entity1, _entity2) local _pos1, _pos2 = GetPosition(_entity1), GetPosition(_entity2) return math.sqrt((_pos1.X - _pos2.X)^2 + (_pos1.Y - _pos2.Y)^2) end ===== Pythagoras ===== **//(Mathe-)Hinweis//:** Die Formel zur Berechnung ist nichts anderes, als der **Satz des Pythagoras**! a^2 + b^2 = c^2 Unsere beiden Punkte (Punkt 1 und Punkt 2) bilden die Punkte A und B eines rechtwinkligen Dreiecks. Ihre Entfernung entspricht also der Länge der Strecke AB ( = Seitenlänge c). Somit ergibt sich c aus der Quadratwurzel (math.sqrt) von (a^2 + b^2).\\ Die Seiten a und b ergeben sich aus der Differenz der jeweiligen X- und Y-Koordinaten der Punkte 1 und 2 (und aufgrund des Quadrierens spielt das Vorzeichen keine Rolle, da das Ergebnis immer positiv ist).