0

I need to generate 4 random numbers, each between [-45 +45] degrees. and if rand%2 = 0 then I want the result (the random number generated to be equal to -angle). Once the 4 random numbers are generated it is requires to scan these angles and find a lock (the point at which the angles meet). Also -3,-2,-1,... +3 in the loop in if statement indicate that the lock takes place within 6 degrees beamwidth. the code works. But can it be simplified? also The objective is to establish a lock between 2 points by scannin elevation and azimuth angles at both points.

  #include <iostream>
  #include <conio.h>
  #include <time.h>
  using namespace std;

  class Cscan
  {
    public:
    int gran, lockaz, lockel;

  };

  int main()
  {
     srand (time(NULL));
    int az1, az2, el1, el2, j, k;


    BS1.lockaz = rand() % 46;
    BS1.lockel = rand() % 46;
    BS2.lockaz = rand() % 46;
    BS2.lockel = rand() % 46;

    k = rand() % 2;
    if(k == 0)
            k = -1;
    BS1.lockaz = k*BS1.lockaz;

    k = rand() % 2;
    if(k == 0)
            k = -1;
    BS1.lockel = k*BS1.lockel;

            k = rand() % 2;
    if(k == 0)
            k = -1;
    BS2.lockaz = k*BS2.lockaz;

    k = rand() % 2;
    if(k == 0)
            k = -1;
    BS2.lockel = k*BS2.lockel;

    for(az1=-45; az1<=45; az1=az1+4)
    {
            for(el1=-45; el1<=45; el1=el1+4)
            {
                    for(az2=-45; az2<=45; az2=az2+4)
                    {
                            for(el2=-45; el2<=45; el2=el2+4)
                            {

           if((az1==BS1.lockaz-3||az1==BS1.lockaz-2||az1==BS1.lockaz-1||az1==BS1.lockaz||az1==BS1.lockaz+1||az1==BS1.lockaz+2||az1==BS1.lockaz+3)&&

           (az2==BS2.lockaz-3||az2==BS2.lockaz-2||az2==BS2.lockaz-1||az2==BS2.lockaz||az2==BS2.lockaz+1||az2==BS2.lockaz+2||az2==BS2.lockaz+3)&&

           (el1==BS1.lockel-3||el1==BS1.lockel-2||el1==BS1.lockel-1||el1==BS1.lockel||el1==BS1.lockel+1||el1==BS1.lockel+2||el1==BS1.lockel+3)&&

            (el2==BS2.lockel-3||el2==BS2.lockel-2||el2==BS2.lockel-1||el2==BS2.lockel||el2==BS2.lockel+1||el2==BS2.lockel+2||el2==BS2.lockel+3))
                                    {      
             cout << "locked \n" << BS1.lockaz << " " << BS1.lockel << " " << BS2.lockaz << " " << BS2.lockel <<endl
              < az1 << " " << el1 << " " << az2 << " " << el2 << endl;
                                                    k = 1;
                                            break;
                                    }
                                    if(k==1)
                                            break;
                            }
                            if(k==1)
                                    break;
                    }
                    if(k==1)
                            break;
            }
            if(k==1)
                    break;
    }
    _getch();
  }       
  • 3
    `[-45;45]` is `[0;90]` shift by 45 to the left. See if you can use that to make your code simpler. – Mat Nov 20 '12 at 10:37
  • so if I shift by 45 to the left I'll still need to select a random number even for the negative range. Can you explain what you meant please? –  Nov 20 '12 at 11:10
  • I don't understand your comment. If you take a random value in [0,X] and remove Y, you'll end up with a random value in [-Y,X-Y]. – Mat Nov 20 '12 at 11:20
  • thank you. SO if I use say BS1.lockaz= rand()%91-45 then will it not be required to use k? –  Nov 20 '12 at 11:25
  • What do you think? Analyze that statement and figure out what it does. If it does what you want, you're good. – Mat Nov 20 '12 at 11:31
  • Actually, now I've rewritten it to be somewhat readable: isn't all this loop business doing nothing but to search `az₁ ≈ BZ₁ₐ && el₁ ≈ BZ₁ₑ && az₂ ≈ BZ₂ₐ && el₂ ≈ BZ₂ₑ`? You could just _read out_ the exact values... – leftaroundabout Nov 20 '12 at 11:47

2 Answers2

2
BS1.lockaz = rand() % 91 - 45;
BS1.lockel = rand() % 91 - 45;
BS2.lockaz = rand() % 91 - 45;
BS2.lockel = rand() % 91 - 45;
pndc
  • 3,710
  • 2
  • 23
  • 34
  • do you mean use BS1.lockaz = rand() % 91 - 45; BS1.lockel = rand() % 91 - 45; BS2.lockaz = rand() % 91 - 45; BS2.lockel = rand() % 91 - 45; to generate negative angles? –  Nov 20 '12 at 10:56
1

Integer angles in degrees? Very questionable. Something "physical" like an angle is normally best expressed as a floating-point number, so I'd first change

typedef double angle;

struct Cscan {  // why class? This is clearly POD
  int gran; //I don't know what gran is. Perhaps this should also be floating-point.
  angle lockaz, lockel;
};

That seems to make it more difficult at first sight because neither the random-range-selection with % works anymore nor is it much use to compare floats for equality. Which is, however, a good thing, because all of this is in fact very bad practise.

If you want to keep using rand() as the random number generator (though I'd suggest std::uniform_real_distribution), write a function to do this:

const double pi = 3.141592653589793;  // Let's use radians internally, not degrees.
const angle rightangle = pi/2.;      //  It's much handier for real calculations.

inline angle deg2rad(angle dg) {return dg * rightangle / 90.;}

angle random_in_sym_rightangle() {
  return rightangle * ( ((double) rand()) / ((double) RAND_MAX) - .5 );
}

Now you'd just do

BS1.lockaz = random_in_sym_rightangle();
BS1.lockel = random_in_sym_rightangle();
BS2.lockaz = random_in_sym_rightangle();
BS2.lockel = random_in_sym_rightangle();

Then you need to do this range-checking. That's again something to put in a dedicated function

bool equal_in_margin(angle theta, angle phi, angle margin) {
  return (theta > phi-margin && theta < phi+margin);
}

Then you do this exhaustive search for locks. This could definitely be done more efficiently, but that's an algorithm issue and has nothing to do with the language. Sticking to the for loops, you can still make them look much nicer by avoiding this explicit break checking. One way is good old goto, I'd propose here you just stick it in an extra function and return when you're done

#define TRAVERSE_SYM_RIGHTANGLE(phi) \
  for ( angle phi = -pi/4.; phi < pi/4.; phi += deg2rad(4) )

int lock_k  // better give this a more descriptive name
      ( const Cscan& BS1, const Cscan& BS2, int k ) {
  TRAVERSE_SYM_RIGHTANGLE(az1) {
    TRAVERSE_SYM_RIGHTANGLE(el1) {
      TRAVERSE_SYM_RIGHTANGLE(az2) {
        TRAVERSE_SYM_RIGHTANGLE(el2) {
          if( equal_in_margin( az1, BS1.lockaz, deg2rad(6.) )
               && equal_in_margin( el1, BS1.lockel, deg2rad(6.) )
               && equal_in_margin( az2, BS1.lockaz, deg2rad(6.) )
               && equal_in_margin( el2, BS2.lockel, deg2rad(6.) ) ) {
            std::cout << "locked \n" << BS1.lockaz << " " << BS1.lockel << " " << BS2.lockaz << " " << BS2.lockel << '\n'
               << az1 << " " << el1 << " " << az2 << " " << el2 << std::endl;
            return 1;
          }
        }
      }
    }
  }
  return k;
}
leftaroundabout
  • 117,950
  • 5
  • 174
  • 319
  • hi I did try this code but i need explanition please. I'm new to C++. I got an error in: int lock_k ( const CScan& BZ1, const CScan& BZ2, init k ) . Where do we have to declare int main() ? and is BZ1 and BZ2 you have indicated in int lock_k // better give this a more descriptive name ( const CScan& BZ1, const CScan& BZ2, init k ) the same as BS1 and BS2? –  Nov 20 '12 at 12:06
  • I get an error in this line as well : inline angle deg2rad(angle dg) {return dg * rightangle / 90} –  Nov 20 '12 at 12:08
  • thank you so much!there is another parameter that needs to be added which is the range. the range should vary between 20m to 800m in steps of 20. for each of these range is it required to determine the lock. Where should I include this? –  Nov 20 '12 at 13:43
  • What "range"? Plaise explain mathematically. – leftaroundabout Nov 20 '12 at 13:51
  • ok I'll explain that. Meanwhile I tried modyfing your code with my existing code. http://ideone.com/jrDzF7 –  Nov 20 '12 at 14:09
  • It doesn't work. I want to use rand function and BS1.lockaz = rand() % 91 - 45;should scan from -45 to +45. so I don't need to use k. Can you tell me why it doesn't work please? –  Nov 20 '12 at 14:10
  • ok this is what I mean: Assume 2 node (host) and (source) each node is scanning an angle [-45 45] in elevation and azimuth. at a particular angle elevation and azimuth for the host and source nide, there is a lock achieved. at this moment I haven't considered the distance between the source and the host. if I consider a distance of 20m between the source and the host, what will the lock angles be. Also If i vary this distance from 20 to 800m in steps of 20m what will the lock angles be? –  Nov 20 '12 at 14:16
  • I don't know what you mean by any of that. If it's supposed to be physically meaningful, you need to have at least _two_ distances that have some relation; one distance alone can't relate to angles for dimensional reasons. Really, I think you should first get the maths clear before trying to hack this in some way. And again: _use radians_, when you get to the real trigonometry it pays off. You can write a `show_as_deg(angle phi)` function if you prefer to display the values in degrees. Regarding the program you posted: don't use `_getch()`, it's from the long-deprecated `conio` library. – leftaroundabout Nov 20 '12 at 14:38
  • thanks again. but in te program you've written const double pi = 3.141592653589793; // Let's use radians internally, not degrees. const angle rightangle = pi/2.; // It's much handier for real calculations. inline angle deg2rad(angle dg) {return dg * rightangle / 90.;} angle random_in_sym_rightangle() { return rightangle * ( ((double) rand()) / ((double) RAND_MAX) - .5 ); } what does this do? does it scan angles from -45 to +45 or 0 to 45? –  Nov 20 '12 at 14:54
  • You can find this out on your own, can't you? Just call it a few times and display the results! – leftaroundabout Nov 20 '12 at 15:01