§ 16. Тып даных структура (struct)

16.2. Выкарыстанне структур для апісання геаметрычных аб’ектаў

Самым простым геаметрычным аб’ектам на плоскасці з’яўляецца пункт, які задаецца сваімі каардынатамі. Пункт апісаны ў прыкладзе 16.1. Пары пунктаў на плоскасці вызначае адрэзак, які апісаны ў прыкладзе 16.5.

Яшчэ адным важным геаметрычным аб’ектам на плоскасці з’яўляецца прамая. У матэматыцы выкарыстоўваюць розныя спосабы апісаць прамую з дапамогай ураўненняў. Ураўненне прамой на плоскасці ў прамавугольнай сістэме каардынат — гэта некаторае ўраўненне з дзвюма пераменнымі x і y, якое ператвараецца ў тоеснасць пры падстаноўцы ў яго каардынат любога пункта гэтай прамой. Любая форма ўраўнення прамой мае параметры. Выкарыстоўваючы параметры ўраўнення, можна апісаць адпаведную структуру (прыклад 16.7). Розныя формы ўраўнення прамой (у большасці выпадкаў) могуць быць прыведзены адна да адной, паколькі яны апісваюць адзін і той жа аб’ект. Выкарыстанне той ці іншай формы ўраўнення прамой залежыць ад задачы. Ураўненне прамой у агульным выглядзе з’яўляецца найбольш універсальным. Любая іншая форма ўраўнення прамой заўсёды можа быць прыведзена да агульнага ўраўнення прамой.

Прыклад 16.8. Вядомы каардынаты двух пунктаў, праз якія праходзіць прамая. Атрымаць запіс ураўнення гэтай прамой у агульным выглядзе.

Этапы выканання задання

I. Зыходныя даныя: пераменная p1 (структура, якая апісвае ўраўненне прамой, што праходзіць праз два пункты).

II. Вынік: пераменная p2 (структура, якая апісвае ўраўненне прамой у агульным выглядзе).

III. Алгарытм рашэння задачы.

  1. Увод зыходных даных. Уводзім каардынаты двух пунктаў і ствараем з іх структуру  p1.
  2. Для таго каб з адной структуры атрымаць іншую, створым функцыю tchk_to_pr.
  3. Для атрымання адпаведных каэфіцыентаў выканаем наступныя тоесныя пераўтварэнні ўраўнення прамой, якая праходзіць праз два пункты.

begin mathsize 18px style left parenthesis x space – space x subscript 1 right parenthesis left parenthesis y subscript 2 – space y subscript 1 right parenthesis space equals space left parenthesis y space – space y subscript 1 right parenthesis left parenthesis x subscript 2 space – space x subscript 1 right parenthesis space left right double arrow
left right double arrow left parenthesis y subscript 2 – space y subscript 1 right parenthesis x space minus left parenthesis y subscript 2 space minus space y subscript 1 right parenthesis space x subscript 1 space minus space left parenthesis x subscript 2 minus space x subscript 1 right parenthesis space y space plus space left parenthesis x subscript 2 minus space x subscript 1 right parenthesis space y subscript 1 equals 0 end style

begin mathsize 18px style A space equals space y subscript 2 space minus space y subscript 1 semicolon space space space B space equals space x subscript 1 space minus space x subscript 2 semicolon space space C space equals space space y subscript 1 x subscript 2 space minus space x subscript 1 y subscript 2 end style

4. Вывад выніку.

IV. Апісанне пераменных: p1, p2 – struct.

Прыклад 16.9. Вядомы каардынаты пункта і каэфіцыенты ўраўнення прамой у агульным выглядзе. Вызначыць, ці належыць пункт прамой.

Этапы выканання задання

I. Зыходныя даныя: пераменная AB (структура, якая апісвае ўраўненне прамой у агульным выглядзе), A(структура, якая апісвае пункт).

II. Вынік: паведамленне «так» або «не».

III. Алгарытм рашэння задачы.

  1. Увод зыходных даных.
  2. Для таго каб праверыць, ці ляжыць пункт на прамой, створым функцыю tchk_na_pr.
  3. Пункт ляжыць на прамой, калі пры падстаноўцы яе каардынат ва ўраўненне прамой атрымаем правільную роўнасць (для агульнага ўраўнення павінны атрымаць 0). Паколькі вылічэнні праходзяць у рэчаісных ліках, то будзем правяраць, што атрыманае значэнне па модулі меншае, чым 10-6. Такой дакладнасці на практыцы звычайна бывае дастаткова.
  4. Вывад выніку.

IV. Апісанне пераменных: A, AB – struct.

Прыклад 16.10. Вядомы каардынаты канцоў адрэзка і каэфіцыенты ўраўнення прамой у агульным выглядзе. Вызначыць, ці маюць прамая і адрэзак агульныя пункты.

Этапы выканання задання

I. Зыходныя даныя: пераменная CD (структура, якая апісвае ўраўненне прамой у агульным выглядзе), АB (структура, якая апісвае адрэзак).

II. Вынік: паведамленне «так» або «не».

III. Алгарытм рашэння задачы.

  1. Увод зыходных даных. Структуру AB ствараем па ўведзеных каардынатах двух пунктаў.
  2. Для таго каб праверыць, ці маюць прамая і адрэзак агульныя пункты, створым функцыю  otr_na_pr.
  3. Адрэзак мае з прамой агульныя пункты, калі выконваецца адна з умоў:

3.1. Адзін з канцоў адрэзка ляжыць на прамой.
3.2. Абодва канцы адрэзка ляжаць на прамой.
3.3. Прамая перасякае адрэзак.

  1. Калі пункт ляжыць на прамой, то пры падстаноўцы яго каардынат ва ўраўненне ў левай частцы агульнага ўраўнення прамой атрымліваем 0. Калі пункт не належыць прамой, то атрымліваем адну з дзвюх няроўнасцей: begin mathsize 16px style A x space plus space B y space plus space C space less than space 0 end style  або A x space plus space B y space plus space C space greater than space 0. Кожная з няроўнасцей вызначае паўплоскасць адносна зададзенай прамой. Прамая перасякае адрэзак, калі яго канцы знаходзяцца ў розных паўплоскасцях адносна зададзенай прамой.
  2. Паколькі вылічэнні праходзяць у рэчаісных ліках, то будзем правяраць, што атрыманае значэнне па модулі меншае, чым 10-6. Такой дакладнасці на практыцы звычайна бывае дастаткова.
  3. Вывад выніку.

IV. Апісанне пераменных: CD, AB – struct.

Прыклад 16.11. Многавугольнік зададзены спісам сваіх вяршынь у парадку абходу. Для кожнай вяршыні вядомы яе каардынаты на плоскасці. Знайсці перыметр многавугольніка.

Этапы выканання задання

I. Зыходныя даныя: n — колькасць пунктаў, a — масіў пунктаў.

II. Вынік: перыметр многавугольніка.

III. Алгарытм рашэння задачы.

  1. Увод зыходных даных. Ствараем масіў з пунктаў і ўводзім каардынаты.
  2. Кожная старана многавугольніка — гэта адрэзак, які злучае вяршыні з суседнімі нумарамі. Для таго каб не апрацоўваць асобна старану, якая злучае апошнюю вяршыню з пачатковай, дададзім каардынаты пачатковай вяршыні ў канец вектара.
  3. Для вылічэння перыметра створым функцыю, якая будзе вылічаць даўжыню адрэзка.
  4. У цыкле перабяром пары суседніх вяршынь і вылічым іх даўжыні. Сума даўжынь — шуканы перыметр.
  5. Вывад выніку. 

IV. Апісанне пераменных: n – int, a – vector<tchk>.

Прыклад 16.7. Формы запісу ўраўнення прамой і адпаведныя ім апісанні структур.

Ураўненне прамой з вуглавым каэфіцыентам: y = kx + l. Уравнение не позволяет описать прямую, параллельную оси OY.

struct pr_ugl_kf

{

  double k, l;

};

Ураўненне прамой у адрэзках: begin mathsize 16px style x over a space plus space y over b space equals space 1. end style Параметры а і b — велічыні адрэзкаў, якія адсякаюцца прамой на восях каардынат. Ураўненне не дазваляе апісаць прамую, якая праходзіць праз пачатак каардынат.

struct pr_v_otr

{

  double a, b;

};

Ураўненне прамой, якая праходзіць праз два пункты begin mathsize 16px style A left parenthesis x subscript 1 comma space space y subscript 1 right parenthesis end style) і  B left parenthesis x subscript 2 comma space space y subscript 2 right parenthesis:

begin mathsize 16px style left parenthesis x space minus space x subscript 1 right parenthesis left parenthesis y subscript 2 space minus space y subscript 1 right parenthesis space equals space left parenthesis y space minus space y subscript 1 right parenthesis left parenthesis x subscript 2 space minus space x subscript 1 right parenthesis end style

struct pr_2_tchk

{

  tchk A, B; 

};

Агульнае ўраўненне прамой:

struct pr

{

  double A, B, C;

};

Прыклад 16.8.

V. Праграма:

#include <iostream>

 

using namespace std;

 

struct tchk

{

  double x, y;

};

 

struct pr_2_tchk

{

    tchk A, B;

};

 

struct pr

{

    double A, B, C;

};

 

pr tchk_to_pr(pr_2_tchk t)

{

  pr t1;

  t1.= t.B.- t.A.y;

  t1.= t.A.- t.B.x;

  t1.= t.A.* t.B.- t.A.* t.B.y;

  return t1;

}

 

int main()

{

  tchk A, B;

  cout << "x1, y1" << endl;

  cin >> A.>> A.y;

  cout << "x2, y2" << endl;

  cin >> B.>> B.y;

  pr_2_tchk p1 = {A, B};

  pr p2 = tchk_to_pr (p1);

  cout << "obschee uravnenie: ";

  cout << p2.<< "x + ";

  cout << p2.<< "y + " << p2.C;

  cout << " = 0" << endl;

  return 0;

}

  VI. Тэсціраванне.

Прыклад 16.9.

V. Праграма:

#include <iostream>

#include <cmath>

 

using namespace std;

 

struct tchk

{

  double x, y;

};

 

struct pr

{

  double A, B, C;

};

 

bool tchk_na_pr(pr p, tchk t)

{

  double z = p.* t.+ p.* t.+ p.C;

  return (abs(z) <= 0.000001);

}

 

int main()

{

  tchk A;

  cout << "koord x, y" << endl;

  cin >> A.>> A.y;

  pr AB;

  cout << "koef A, B, C" << endl;

  cin >> AB.>> AB.>> AB.C;

  if (tchk_na_pr(AB, A))

    cout << "da" << endl;

  else

    cout << "net" << endl;

  return 0;

}

 VI.  Тэсціраванне.

Прыклад 16.10.

V. Праграмма:

#include <iostream>

#include <cmath>

 

using namespace std;

 

struct tchk

{

  double x, y;

};

 

struct otrezok

{

  tchk beg, en;

};

 

struct pr

{

  double A, B, C;

};

 

bool otr_na_pr(pr p, otrezok t)

{

  double z1, z2;

  z1 = p.* t.beg.+ p.* t.beg.+ p.C;

  z2 = p.* t.en.+ p.* t.en.+ p.C;

  return (z1 * z2 < 0 ||

        abs(z1 * z2) <= 0.000001);

}

 

int main()

{

  tchk A, B;

  cout << "koord x1, y1" << endl;

  cin >> A.>> A.y;

  cout << "koord x2, y2" << endl;

  cin >> B.>> B.y;

  otrezok AB = {A, B};

  pr CD;

  cout << "koef A, B, C" << endl;

  cin >> CD.>> CD.>> CD.C;

  if (otr_na_pr(CD, AB))

    cout << "da" << endl;

  else

    cout << "net" << endl;

  return 0;

}

  VI. Тэсціраванне.

Адрэзак цалкам ляжыць на прамой.

Адзін канец адрэзка ляжыць на прамой.

Прамая перасякае адрэзак.

Няма агульных пунктаў.

Прыклад 16.11.

V. Праграма:

#include <iostream>

#include <vector>

#include <cmath>

 

using namespace std;

 

struct tchk

{

  double x, y;

};

 

double dlina (tchk A, tchk B)

{

  double dl;

  dl = sqrt((A.- B.x) * (A.- B.x) +

            (A.- B.y) * (A.- B.y));

  return dl;

}

 

int main()

{

  int n;

  cout << "n = ";

  cin >> n;

  vector <tchk> a(n);

  for (int i = 0; i < n; i++)

    cin >> a[i].>> a[i].y;

  a.push_back(a[0]);

  double p = 0;

  for (int i = 0; i < n; i++)

    p += dlina(a[i], a[+ 1]);

  cout << "p = " << p << endl;

  return 0;

}

 VI. Тэсціраванне.