How can I scale a 2D rotation vector without trig functions?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







1















I have a normalized 2D vector that I am using to rotate other 2D vectors. In one instance it indicates "spin" (or "angular momentum") and is used to rotate the "orientation" of a simple polygon. My vector class contains this method:



rotateByXY(x, y) {
let rotX = x * this.x - y * this.y;
let rotY = y * this.x + x * this.y;
this.x = rotX;
this.y = rotY;
}


So far, this is all efficient and uses no trig whatsoever.



However, I want the "spin" to decay over time. This means that the angle of the spin should tend towards zero. And here I'm at a loss as to how to do this without expensive trig calls like this:



let angle = Math.atan2(spin.y, spin.x);
angle *= SPIN_DECAY;
spin = new Vector2D(Math.cos(angle), Math.sin(angle));


Is there a better/faster way to accomplish this?










share|improve this question


















  • 1





    Simple formulas exist only for SPIN_DECAY = 1/2 (and for arithmetic progression an[i] = an0 - i*da). Otherwise it would better to store angle to avoid atan2. If you apply the same rotation to multiple points, single evaluation of sin/cos per step is not so bad.

    – MBo
    Jan 4 at 5:35








  • 1





    what about this: How to calculate rocket? see the rotation math at the end... beware it works only for rotations up to 90deg and the rotation is not linear but not too far from it either and works for any dimensionality...the dimming is done simply by decreasing the dang0 or by dang0*=0.95 each iteration etc ... you do not need the acos for computing a as you already know how much your original rotation rotates ...

    – Spektre
    Jan 4 at 11:00













  • Another idea: what about approximating your trigonometric functions with their Taylor expansions?

    – Dominik Mokriš
    Jan 17 at 20:03











  • @DominikMokriš, that sounds intriguing. Can you say more and/or provide details? Not quite sure how to implement that. BTW, I did consider something like this lookup: int iX = int((spin.x + 1) * 100); int iY = int((spin.y + 1) * 100); spin = DecayLookupX[iX][iY]; Where DecayLookup is a 200 x 200 array of pre-calculated vectors (could be tuned). A bit rough, but would work for a constant decay.

    – Scott Schafer
    Jan 19 at 0:28




















1















I have a normalized 2D vector that I am using to rotate other 2D vectors. In one instance it indicates "spin" (or "angular momentum") and is used to rotate the "orientation" of a simple polygon. My vector class contains this method:



rotateByXY(x, y) {
let rotX = x * this.x - y * this.y;
let rotY = y * this.x + x * this.y;
this.x = rotX;
this.y = rotY;
}


So far, this is all efficient and uses no trig whatsoever.



However, I want the "spin" to decay over time. This means that the angle of the spin should tend towards zero. And here I'm at a loss as to how to do this without expensive trig calls like this:



let angle = Math.atan2(spin.y, spin.x);
angle *= SPIN_DECAY;
spin = new Vector2D(Math.cos(angle), Math.sin(angle));


Is there a better/faster way to accomplish this?










share|improve this question


















  • 1





    Simple formulas exist only for SPIN_DECAY = 1/2 (and for arithmetic progression an[i] = an0 - i*da). Otherwise it would better to store angle to avoid atan2. If you apply the same rotation to multiple points, single evaluation of sin/cos per step is not so bad.

    – MBo
    Jan 4 at 5:35








  • 1





    what about this: How to calculate rocket? see the rotation math at the end... beware it works only for rotations up to 90deg and the rotation is not linear but not too far from it either and works for any dimensionality...the dimming is done simply by decreasing the dang0 or by dang0*=0.95 each iteration etc ... you do not need the acos for computing a as you already know how much your original rotation rotates ...

    – Spektre
    Jan 4 at 11:00













  • Another idea: what about approximating your trigonometric functions with their Taylor expansions?

    – Dominik Mokriš
    Jan 17 at 20:03











  • @DominikMokriš, that sounds intriguing. Can you say more and/or provide details? Not quite sure how to implement that. BTW, I did consider something like this lookup: int iX = int((spin.x + 1) * 100); int iY = int((spin.y + 1) * 100); spin = DecayLookupX[iX][iY]; Where DecayLookup is a 200 x 200 array of pre-calculated vectors (could be tuned). A bit rough, but would work for a constant decay.

    – Scott Schafer
    Jan 19 at 0:28
















1












1








1


0






I have a normalized 2D vector that I am using to rotate other 2D vectors. In one instance it indicates "spin" (or "angular momentum") and is used to rotate the "orientation" of a simple polygon. My vector class contains this method:



rotateByXY(x, y) {
let rotX = x * this.x - y * this.y;
let rotY = y * this.x + x * this.y;
this.x = rotX;
this.y = rotY;
}


So far, this is all efficient and uses no trig whatsoever.



However, I want the "spin" to decay over time. This means that the angle of the spin should tend towards zero. And here I'm at a loss as to how to do this without expensive trig calls like this:



let angle = Math.atan2(spin.y, spin.x);
angle *= SPIN_DECAY;
spin = new Vector2D(Math.cos(angle), Math.sin(angle));


Is there a better/faster way to accomplish this?










share|improve this question














I have a normalized 2D vector that I am using to rotate other 2D vectors. In one instance it indicates "spin" (or "angular momentum") and is used to rotate the "orientation" of a simple polygon. My vector class contains this method:



rotateByXY(x, y) {
let rotX = x * this.x - y * this.y;
let rotY = y * this.x + x * this.y;
this.x = rotX;
this.y = rotY;
}


So far, this is all efficient and uses no trig whatsoever.



However, I want the "spin" to decay over time. This means that the angle of the spin should tend towards zero. And here I'm at a loss as to how to do this without expensive trig calls like this:



let angle = Math.atan2(spin.y, spin.x);
angle *= SPIN_DECAY;
spin = new Vector2D(Math.cos(angle), Math.sin(angle));


Is there a better/faster way to accomplish this?







geometry 2d trigonometry






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 4 at 0:22









Scott SchaferScott Schafer

1067




1067








  • 1





    Simple formulas exist only for SPIN_DECAY = 1/2 (and for arithmetic progression an[i] = an0 - i*da). Otherwise it would better to store angle to avoid atan2. If you apply the same rotation to multiple points, single evaluation of sin/cos per step is not so bad.

    – MBo
    Jan 4 at 5:35








  • 1





    what about this: How to calculate rocket? see the rotation math at the end... beware it works only for rotations up to 90deg and the rotation is not linear but not too far from it either and works for any dimensionality...the dimming is done simply by decreasing the dang0 or by dang0*=0.95 each iteration etc ... you do not need the acos for computing a as you already know how much your original rotation rotates ...

    – Spektre
    Jan 4 at 11:00













  • Another idea: what about approximating your trigonometric functions with their Taylor expansions?

    – Dominik Mokriš
    Jan 17 at 20:03











  • @DominikMokriš, that sounds intriguing. Can you say more and/or provide details? Not quite sure how to implement that. BTW, I did consider something like this lookup: int iX = int((spin.x + 1) * 100); int iY = int((spin.y + 1) * 100); spin = DecayLookupX[iX][iY]; Where DecayLookup is a 200 x 200 array of pre-calculated vectors (could be tuned). A bit rough, but would work for a constant decay.

    – Scott Schafer
    Jan 19 at 0:28
















  • 1





    Simple formulas exist only for SPIN_DECAY = 1/2 (and for arithmetic progression an[i] = an0 - i*da). Otherwise it would better to store angle to avoid atan2. If you apply the same rotation to multiple points, single evaluation of sin/cos per step is not so bad.

    – MBo
    Jan 4 at 5:35








  • 1





    what about this: How to calculate rocket? see the rotation math at the end... beware it works only for rotations up to 90deg and the rotation is not linear but not too far from it either and works for any dimensionality...the dimming is done simply by decreasing the dang0 or by dang0*=0.95 each iteration etc ... you do not need the acos for computing a as you already know how much your original rotation rotates ...

    – Spektre
    Jan 4 at 11:00













  • Another idea: what about approximating your trigonometric functions with their Taylor expansions?

    – Dominik Mokriš
    Jan 17 at 20:03











  • @DominikMokriš, that sounds intriguing. Can you say more and/or provide details? Not quite sure how to implement that. BTW, I did consider something like this lookup: int iX = int((spin.x + 1) * 100); int iY = int((spin.y + 1) * 100); spin = DecayLookupX[iX][iY]; Where DecayLookup is a 200 x 200 array of pre-calculated vectors (could be tuned). A bit rough, but would work for a constant decay.

    – Scott Schafer
    Jan 19 at 0:28










1




1





Simple formulas exist only for SPIN_DECAY = 1/2 (and for arithmetic progression an[i] = an0 - i*da). Otherwise it would better to store angle to avoid atan2. If you apply the same rotation to multiple points, single evaluation of sin/cos per step is not so bad.

– MBo
Jan 4 at 5:35







Simple formulas exist only for SPIN_DECAY = 1/2 (and for arithmetic progression an[i] = an0 - i*da). Otherwise it would better to store angle to avoid atan2. If you apply the same rotation to multiple points, single evaluation of sin/cos per step is not so bad.

– MBo
Jan 4 at 5:35






1




1





what about this: How to calculate rocket? see the rotation math at the end... beware it works only for rotations up to 90deg and the rotation is not linear but not too far from it either and works for any dimensionality...the dimming is done simply by decreasing the dang0 or by dang0*=0.95 each iteration etc ... you do not need the acos for computing a as you already know how much your original rotation rotates ...

– Spektre
Jan 4 at 11:00







what about this: How to calculate rocket? see the rotation math at the end... beware it works only for rotations up to 90deg and the rotation is not linear but not too far from it either and works for any dimensionality...the dimming is done simply by decreasing the dang0 or by dang0*=0.95 each iteration etc ... you do not need the acos for computing a as you already know how much your original rotation rotates ...

– Spektre
Jan 4 at 11:00















Another idea: what about approximating your trigonometric functions with their Taylor expansions?

– Dominik Mokriš
Jan 17 at 20:03





Another idea: what about approximating your trigonometric functions with their Taylor expansions?

– Dominik Mokriš
Jan 17 at 20:03













@DominikMokriš, that sounds intriguing. Can you say more and/or provide details? Not quite sure how to implement that. BTW, I did consider something like this lookup: int iX = int((spin.x + 1) * 100); int iY = int((spin.y + 1) * 100); spin = DecayLookupX[iX][iY]; Where DecayLookup is a 200 x 200 array of pre-calculated vectors (could be tuned). A bit rough, but would work for a constant decay.

– Scott Schafer
Jan 19 at 0:28







@DominikMokriš, that sounds intriguing. Can you say more and/or provide details? Not quite sure how to implement that. BTW, I did consider something like this lookup: int iX = int((spin.x + 1) * 100); int iY = int((spin.y + 1) * 100); spin = DecayLookupX[iX][iY]; Where DecayLookup is a 200 x 200 array of pre-calculated vectors (could be tuned). A bit rough, but would work for a constant decay.

– Scott Schafer
Jan 19 at 0:28














1 Answer
1






active

oldest

votes


















1














If it's really the trigonometric functions what is slowing down your computation, you might try to approximate them with their Taylor expansions.



For x close to zero the following identities hold:



cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! + ...
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ...
atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...


Based on the degree of accuracy you need for your application you can trim the series. For instance,



cos(x) = 1 - (x^2)/2


with an error of the order of x^3 (actually, x^4, as the term with x^3 is zero anyway).



However, I don't think that this is going to solve your problem: the actual implementation of atan is likely to be already using the same trick, written by someone with lots of experience of speeding these things up. So this is not really a proper answer but I hope it could still be useful.






share|improve this answer
























  • Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

    – Scott Schafer
    Jan 23 at 0:57












Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54031622%2fhow-can-i-scale-a-2d-rotation-vector-without-trig-functions%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














If it's really the trigonometric functions what is slowing down your computation, you might try to approximate them with their Taylor expansions.



For x close to zero the following identities hold:



cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! + ...
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ...
atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...


Based on the degree of accuracy you need for your application you can trim the series. For instance,



cos(x) = 1 - (x^2)/2


with an error of the order of x^3 (actually, x^4, as the term with x^3 is zero anyway).



However, I don't think that this is going to solve your problem: the actual implementation of atan is likely to be already using the same trick, written by someone with lots of experience of speeding these things up. So this is not really a proper answer but I hope it could still be useful.






share|improve this answer
























  • Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

    – Scott Schafer
    Jan 23 at 0:57
















1














If it's really the trigonometric functions what is slowing down your computation, you might try to approximate them with their Taylor expansions.



For x close to zero the following identities hold:



cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! + ...
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ...
atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...


Based on the degree of accuracy you need for your application you can trim the series. For instance,



cos(x) = 1 - (x^2)/2


with an error of the order of x^3 (actually, x^4, as the term with x^3 is zero anyway).



However, I don't think that this is going to solve your problem: the actual implementation of atan is likely to be already using the same trick, written by someone with lots of experience of speeding these things up. So this is not really a proper answer but I hope it could still be useful.






share|improve this answer
























  • Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

    – Scott Schafer
    Jan 23 at 0:57














1












1








1







If it's really the trigonometric functions what is slowing down your computation, you might try to approximate them with their Taylor expansions.



For x close to zero the following identities hold:



cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! + ...
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ...
atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...


Based on the degree of accuracy you need for your application you can trim the series. For instance,



cos(x) = 1 - (x^2)/2


with an error of the order of x^3 (actually, x^4, as the term with x^3 is zero anyway).



However, I don't think that this is going to solve your problem: the actual implementation of atan is likely to be already using the same trick, written by someone with lots of experience of speeding these things up. So this is not really a proper answer but I hope it could still be useful.






share|improve this answer













If it's really the trigonometric functions what is slowing down your computation, you might try to approximate them with their Taylor expansions.



For x close to zero the following identities hold:



cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! + ...
sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ...
atan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ...


Based on the degree of accuracy you need for your application you can trim the series. For instance,



cos(x) = 1 - (x^2)/2


with an error of the order of x^3 (actually, x^4, as the term with x^3 is zero anyway).



However, I don't think that this is going to solve your problem: the actual implementation of atan is likely to be already using the same trick, written by someone with lots of experience of speeding these things up. So this is not really a proper answer but I hope it could still be useful.







share|improve this answer












share|improve this answer



share|improve this answer










answered Jan 21 at 19:18









Dominik MokrišDominik Mokriš

4041213




4041213













  • Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

    – Scott Schafer
    Jan 23 at 0:57



















  • Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

    – Scott Schafer
    Jan 23 at 0:57

















Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

– Scott Schafer
Jan 23 at 0:57





Ah. Thanks for that explanation. This might be worth looking into. Although since my decay should be constant I think I might be able to get away with a pre-calculated lookup table. Appreciate it though!

– Scott Schafer
Jan 23 at 0:57




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54031622%2fhow-can-i-scale-a-2d-rotation-vector-without-trig-functions%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Monofisismo

Angular Downloading a file using contenturl with Basic Authentication

Olmecas