| 12-10-2007, 09:08 AM | #1 |
Since I managed to derive (myself, seems like no one was up to the challange that I specified here http://www.wc3campaigns.net/showthread.php?t=98175, it was quite difficult I must say, it took me 5 hours to do) the 4 points that form a trapezium of the cameras current view for a player, I now need to find a random point inside this trapazoid. Firstly here is the code if anyone is intereste, x1,y1,x2,y2,x3,y3 and x4,y4 are the 4 points that will form a trapezium of the current cameras view, it isn't 100% accurate (you can play around with the constants) but accurate enough, and it is compatible with rotations done by insert/delete and pitch through mouse scroll (or pageup/pagedown) JASS:local real rotation = GetCameraField(CAMERA_FIELD_ROTATION) local real distance = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) local real aoa = GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK) local real eye = GetCameraEyePositionZ() local real topbound = 11/distance * 180000 local real midbound = distance/11 * 6 local real lowbound = distance/11 * 5 local real highboundmodifier = 957481 local real verticalhighbound = highboundmodifier * 1/eye local real verticallowbound = 100 *aoa local real base = Atan2(verticalhighbound,topbound) local real base2 = Atan2(verticallowbound,lowbound) local real angle = base - bj_PI/2 + rotation local real angle2 = base + bj_PI/2 - rotation local real angle3 = base2 - bj_PI/2 + rotation local real angle4 = base2 + bj_PI/2 - rotation local real dist1 = SquareRoot((topbound*topbound) + (verticalhighbound*verticalhighbound)) local real dist2 = SquareRoot((verticallowbound*verticallowbound) + (lowbound * lowbound)) local real x =GetCameraTargetPositionX() local real y = GetCameraTargetPositionY() //Point at top right local real x1 = x+dist1 * Cos(angle) local real y1 = y +dist1 * Sin(angle) //Point at top left local real x2 = x+dist1 * Cos(bj_PI - angle2) local real y2 = y +dist1 * Sin(bj_PI - angle2) //Point at bottom right local real x3 = x+dist2 * Cos(-angle4) local real y3 = y +dist2 * Sin(-angle2) //Point at bottom left local real x4 = x+dist2 * Cos(bj_PI + angle3) local real y4 = y +dist2 * Sin(bj_PI + angle) Basically what I need to do now is to find the most efficient way of finding a random point inside this trapezium. Note that the 4 points specified will always form a polygon that is a trapezium, and the trapezium will always be shorter at the bottom and longer at the top, the changing values of the points will only rotate the trapeziuem (never past 180 or pi degrees) and will only skew it, i.e. refer to this diagram NOTE: When I mean efficient, I really do mean efficient, I want the minimum amount of calculations done. This will be done within a large loop so I need as little opcode operations as possible as usual rep for anyone who helps |
| 12-10-2007, 11:42 AM | #2 |
Well, i don't have WE atm, but this is the code i figured out. JASS:struct RPTrap real x real y endstruct function RandomTrap takes real x, real y, real angle, real d0, real d1, real d2, real h returns RPTrap local RPTrap dat = RPTrap.create() local real rv local real cv1 = GetRandomReal(0,d0) local real cv2 if cv1 < d1 then set rv = cv1/d1 set cv2 = GetRandomReal(0,rv) * h * -1 elseif cv1 > d0-d2 then set rv = 1-((cv-(d0-d2))/d2) set cv2 = GetRandomReal(0,rv) * h * -1 elseif set cv2 = GetRandomReal(0,h) endif set dat.x = cv1 * Cos(angle) + cv1 * Cos(angle-(bj_PI/2)) + x set dat.y = cv2 * Sin(angle) + cv2 * Sin(angle-(bj_PI/2)) + y return dat endfunction Sorry, i forgot to mention that x and y are the x and y coordinates of the x2,y2 point. ---Edit2--- oh man i wrote some crap at the end... fixed it hopefully ... |
| 12-10-2007, 10:29 PM | #3 | |
Quote:
Thanks for your help but Im unsre about the arguments that are being fed into your function. What I created will return 4 points that will always form a trapezium however your function has angles, one x/y point (this one I know is x2,y2), 3 distance reals and a h (assuming its height). Would you be able to rewrite the function so It uses the 4 points or explain how those arguments relate to the trapezium I am going to rep you for your help though, thx |
| 12-10-2007, 11:38 PM | #4 |
http://www.cgafaq.info/wiki/Random_Point_In_Triangle here is the formula, have fun :) TIP: a trapezium is formed by 2 triangles |
| 12-11-2007, 12:06 AM | #5 | |
Quote:
You can also use 4 triangles if you want to be sadistic :D |
| 12-11-2007, 12:13 AM | #6 |
Thanks heaps Mad Lion, just the help I needed (got it now) |
| 12-11-2007, 01:19 AM | #7 |
This is not over it seems. |
| 12-11-2007, 01:25 AM | #9 |
Will you be so kind to also make pings at four corners of trapezium at the same time you ping a random point so we actually see that you got the right thing? |
| 12-11-2007, 01:31 AM | #10 |
Here it is, the red pings are the 4 corner points of the trapezium, the code is posted as well JASS:local real ax = GetRandomReal(0,1) local real ay = GetRandomReal(0,1) local real bx = GetRandomReal(0,1) local real by = GetRandomReal(0,1) local real cx = 1-ax-bx local real cy = 1-ay-by local real a2x = GetRandomReal(0,1) local real a2y = GetRandomReal(0,1) local real b2x = GetRandomReal(0,1) local real b2y = GetRandomReal(0,1) local real c2x = 1-a2x-b2x local real c2y = 1-a2y-b2y local integer tri = GetRandomInt(1,2) loop exitwhen counter > 12 if GetPlayerSlotState(Player(counter -1)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(counter - 1)) == MAP_CONTROL_USER then if GetLocalPlayer() == Player(counter-1) then //Get and set all camera data set camerax = GetCameraTargetPositionX() set cameray = GetCameraTargetPositionY() set rotation = GetCameraField(CAMERA_FIELD_ROTATION) set distance = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) set aoa = GetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK) set eye = GetCameraEyePositionZ() set topbound = 11/distance * 180000 set midbound = distance/11 * 6 set lowbound = distance/11 * 5 set highboundmodifier = 957481 set verticalhighbound = highboundmodifier * 1/eye set verticallowbound = 100 *aoa set base = Atan2(verticalhighbound,topbound) set base2 = Atan2(verticallowbound,lowbound) set angle = base - bj_PI/2 + rotation set angle2 = base + bj_PI/2 - rotation set angle3 = base2 - bj_PI/2 + rotation set angle4 = base2 + bj_PI/2 - rotation set dist1 = SquareRoot((topbound*topbound) + (verticalhighbound*verticalhighbound)) set dist2 = SquareRoot((verticallowbound*verticallowbound) + (lowbound * lowbound)) //Point at top right set x1 = camerax+dist1 * Cos(angle) set y1 = cameray +dist1 * Sin(angle) //Point at top left set x2 = camerax+dist1 * Cos(bj_PI - angle2) set y2 = cameray +dist1 * Sin(bj_PI - angle2) //Point at bottom right set x3 = camerax+dist2 * Cos(-angle4) set y3 = cameray +dist2 * Sin(-angle2) //Point at bottom left set x4 = camerax+dist2 * Cos(bj_PI + angle3) set y4 = cameray +dist2 * Sin(bj_PI + angle) endif if tri == 1 then if GetLocalPlayer() == Player(counter-1) then set x = ax * x2 + bx * x1 + cx * x3 set y = ay * y2 + by * y1 + cy * y3 endif else if GetLocalPlayer() == Player(counter-1) then set x = a2x * x2 + b2x * x3 + c2x * x4 set y = a2y * y2 + b2y * y3 + c2y * y4 endif endif loop exitwhen counter2 > udg_AMHS_FogBuffer if GetLocalPlayer() == Player(counter-1) then if IsVisibleToPlayer(x,y,Player(counter-1)) then set check = false else set check = true set counter2 = udg_AMHS_FogBuffer + 1 endif endif set counter2 = counter2 + 1 endloop if GetLocalPlayer() == Player(counter-1) then //if check then call PingMinimap(x,y,0.5) call PingMinimapEx(x1,y1,0.5,255,0,0,false) call PingMinimapEx(x2,y2,0.5,255,0,0,false) call PingMinimapEx(x3,y3,0.5,255,0,0,false) call PingMinimapEx(x4,y4,0.5,255,0,0,false) set e = AddSpecialEffect("Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl",x,y) call DestroyEffect(e) //endif endif endif set counter = counter + 1 endloop |
| 12-11-2007, 01:35 AM | #11 |
JASS:local real ax = GetRandomReal(0,1) local real ay = GetRandomReal(0,1) local real bx = GetRandomReal(0,1) local real by = GetRandomReal(0,1) local real cx = 1-ax-bx local real cy = 1-ay-by local real a2x = GetRandomReal(0,1) local real a2y = GetRandomReal(0,1) local real b2x = GetRandomReal(0,1) local real b2y = GetRandomReal(0,1) local real c2x = 1-a2x-b2x local real c2y = 1-a2y-b2y You implemented that algorithm bad. a+b+c should be 1 EDIT: (ups) JASS:set a = GetRandomReal(0, 1) set b = 1-GetRandomReal(a, 1) set c = 1-a-b |
| 12-11-2007, 01:47 AM | #12 |
Working <3 Cohadar |
| 12-11-2007, 01:57 AM | #13 |
Btw what is <3 ? |
| 12-11-2007, 08:43 AM | #14 | |
Quote:
Turn your head sideways and look harder There was another problem with the method, when the trapezium was skewed (by pitching with mouse scroll) it sometimes specified an invalid point over the left hand side and the points werent as random as they should be. However when I split the trapezium into 3 triangles, (5th points was midpoint of 1st and 2nd point) then the problem stopped occuring |
| 12-11-2007, 09:18 AM | #15 |
The points were "not random as they should be" because this is not uniform distribution: JASS:set a = GetRandomReal(0, 1) set b = 1-GetRandomReal(a, 1) set c = 1-a-b I just optimized it at the cost of absolute "randomness" uniform distribution: JASS:set a = GetRandomReal(0, 1) set b = GetRandomReal(0, 1) if a+b > 1 then set a = 1 - a set b = 1 - b endif set c = 1-a-b |
