2025(e)ko otsailaren 24(a), astelehena

Ariketa 39 | Triangeluaren Zirkunzentroa

ZER DAKIDAN:
Ariketa bati dagokion kodifikazioa programa monolitiko batean idazteko gai naiz eta programa moduluetan zatitzeko gai naiz.



ZER IKASIKO DUDAN:
Programa bat zatitzen ikasiko dut moduluak sortuz, modulu horiek azpiprogramak deitzen dira eta bi motatakoak izan daitezke: funtzioak edo prozedurak. Ikas dezagun noiz erabili funtzioa eta noiz prozedura.




ESKATZEN DEN PROGRAMA

Zirkunzentro: Poligono batera zirkunskribatua dagoen zirkunferentziaren zentroa. Poligonoa triangelua bada, hiru erdibitzaileek elkar ebakitzen duten puntua da zirkunzentroa.

Triangeluaren zirkunzentroa eta zirkunferentzia zirkunskribatua

Triangeluaren zirkunzentroa non kokatzen den triangeluak dituen angeluen araberakoa da. Horrela, triangelu angeluzuzena bada zirkunzentroa triangeluaren hipotenusaren gainean kokatzen da, baina angelu kamutsa badu zirkunzentroa triangelutik kanpo geratzen da eta triangeluaren barruan angelu zorrotzak baditu.

Zirkunzentroaren kokapena triangeluarekiko

   TRIANGELUAREN HIRU ERPINAK:
  • A puntua eta B puntua segmentu horizontal batean daude    
  • A puntua eta B puntua ez dira bat
  • C puntua ez dago AB segmentu horizontalean
    (beraz, fCy koordenatua desberdin fAy koordenatua)
  • C puntua A puntua eta B puntuaren artean dago
    (beraz, fCx koordenatuaren balioa fAx eta fBx artekoa da)

Goiko baldintzak betetzen dituzten triangeluaren hiru erpinen fAx, fAy, fBx, fBy, fCx eta fCy koordenatuak datutzat emanik, zirkunferentzia zirkunskribatuaren fR erradioa kalkulatu ondoko formula erabiliz:

    fR = (fA*fB*fC) / (4*fS);         Non fA, fB eta fC triangeluaren aldeak diren eta fS azalera den


Horregatik, triangeluaren fA, fB eta fC aldeen luzerak eta fS azalera kalkulatu behar dira. Aldeak lortzeko Pitagorasen teorema aplikatuko dugu funtzio baten bitartez, eta fS azalera eskuratzeko ondoko formula barneratzen duen funtzioa idatziko dugu:

fS = 0.5*(fAx*fBy + fBx*fCy + fCx*fAy - fCx*fBy - fBx*fAy - fAx*fCy);

Triangelua eta zenbait aldagairen adierazpenak:
koordenatuak, distantziak, azalera, ...

Zirkunferentziaren erradioa zehaztu ondoren, zirkunferentziaren Z zentroa kalkulatuko dugu, hots, fZx eta fZy koordenatuak kalkulatuko ditugu. Horretarako, komenigarria izango da Ariketa 16 | Triangeluaren azalera ariketa birpasatzea, non zuzen bat adierazteko malda-desplazamendua bikotea erabiltzen den. Dagokigun ariketa honetan AC eta BC segmentuen maldak eta desplazamenduak eskuratzen dira, eta horiei esker AC eta BC segmentu biren ebakidura (fZx, fZy) puntuaren koordenatuak kalkulatzen dira.
Irudiko P puntua, ariketa honetan bilatzen den Z zentroa litzateke

Zirkunferentziaren erradioa eta zentroa ezagunak direla, frogatzerik dago zirkunferentzia horrek triangelua zirkunskribatzen duen, horretarako hiru erpinek zirkunferentziaren formula bete beharko dute. Hauxe da ariketaren programa nagusia eta azpiprogramen goiburuak:
/* Ariketa-39_TriangeluarenZirkunzentroa: sarrerako eta irteerako parametroak */

// A puntua eta B puntua segmentu horizontal batean daude
// A puntua eta B puntua ez dira bat
// C puntua ez dago AB segmentu horizontalean
// AC segmentua ez da bertikala
// BC segmentua ez da bertikala

// 39. ariketa: A, B eta C erpinez triangelua definitu (6 koordenatu). 

//     AB aldea horizontala izango da eta ABC triangeluari dagokion    
//     zirkunferentzia zirkunskribatuaren R erradioa kalkulatu.        
//     ABC triangeluari dagokion zirkunferentzia zirkunskribatuaren Z  
//     zentroaren bi koordenatuak Zx eta Zy kalkulatu.                 

//     Datuak hiru erpinen koordenatuak dira eta prozedura batean      
//     hartzen dira, adibidez: (0.0, 0.0), (4.0, 0.0) eta (2.0, 2.0)   


#include <stdio.h>
#include <math.h>

// ErpinakEskuratu: irteerako 6 parametro
void ErpinakEskuratu(float *fAx, float *fAy, float *fBx, float *fBy, float *fCx, float *fCy);
// AldeaLortu: sarrerako 4 parametro, emaitza float
float AldeaLortu(float f1x, float f1y, float f2x, float f2y);
// AzaleraLortu: sarrerako 6 parametro, emaitza float
float AzaleraLortu(float fAx, float fAy, float fBx, float fBy, float fCx, float fCy);
// ErrradioaLortu: sarrerako 4 parametro, emaitza float
float ErrradioaLortu(float fA, float fB, float fC, float fS);
// ZuzenarenMalda: sarrerako 4 parametro, emaitza float
float ZuzenarenMalda(float fPx, float fPy, float fQx, float fQy);
// SegmentuarenErdia: sarrerako 4 parametro, irteerako 2 parametro
void SegmentuarenErdia(float fPx, float fPy,
                       float fQx, float fQy,
                       float *fErdiaPQx, float *fErdiaPQy);
// ZentroaKalkulatu: sarrerako 4 parametro, irteerako 2 parametro
void ZentroaKalkulatu(float fM1, float fM2, float fD1, float fD2, float *fZx, float *fZy);
// ErpinaZirkunferentzianDago: sarrerako 5 parametro, emaitza int
int ErpinaZirkunferentzianDago(float fZx, float fZy, float fR, float fAx, float fAy);


int main()
{
    float fAx, fAy, fBx, fBy, fCx, fCy, fZx, fZy;       // koordenatuak
    float fErdiaACx, fErdiaACy, fErdiaBCx, fErdiaBCy;   // koordenatuak
    float fA, fB, fC, fR;                               // distantziak
    float fS;                                           // azalera
    float fMaldaAC, fPendikularraAC;                    // maldak
    float fMaldaBC, fPendikularraBC;                    // maldak
    float fDesplazamendu1, fDesplazamendu2;             // distantziak

    printf("\n\n\n");

    // triangeluaren hiru erpinak irakurri
    ErpinakEskuratu(&fAx, &fAy, &fBx, &fBy, &fCx, &fCy);

    printf("\n");

    // triangeluaren hiru aldeak lortu
    fA = AldeaLortu(fBx, fBy, fCx, fCy);    // BC segmentuaren luzera lortu
    fB = AldeaLortu(fAx, fAy, fCx, fCy);    // AC segmentuaren luzera lortu
    fC = AldeaLortu(fAx, fAy, fBx, fBy);    // AB segmentuaren luzera lortu

    printf("   fA aldea = %.2lf m\n", fA);  // BC segmentuaren luzera erakutsi
    printf("   fB aldea = %.2lf m\n", fB);  // AC segmentuaren luzera erakutsi
    printf("   fC aldea = %.2lf m\n", fC);  // AB segmentuaren luzera erakutsi

    // triangeluaren azalera kalkulatu erpinak ezagunak izatean
    fS = AzaleraLortu(fAx, fAy, fBx, fBy, fCx, fCy);

    printf("   fS azal. = %.3lf m^2\n\n", fS);

    // erradioa kalkulatzeko formula: (rA·rB·rC)/(4·rS)
    fR = ErrradioaLortu(fA, fB, fC, fS);

    printf("   fR erra. = %.3lf m\n\n", fR);

    // AC perpendikularraren malda
    fMaldaAC = ZuzenarenMalda(fAx, fAy, fCx, fCy);
    printf("   AC malda = %.2lf\n", fMaldaAC);
    fPendikularraAC = -(1 / fMaldaAC);
    printf("   AC perp. = %.2lf\n", fPendikularraAC);

    // AC perpendikularren zuzenak duen desplazamendua
    SegmentuarenErdia(fAx, fAy, fCx, fCy, &fErdiaACx, &fErdiaACy);
    printf("   AC erdia = (%.2lf, %.2lf)\n", fErdiaACx, fErdiaACy);
    fDesplazamendu1 = fErdiaACy + fErdiaACx / fMaldaAC;
    printf("   Desplaz1 = %.2lf m\n\n", fDesplazamendu1);

    // BC perpendikularraren malda
    fMaldaBC = ZuzenarenMalda(fBx, fBy, fCx, fCy);
    printf("   BC malda = %.2lf\n", fMaldaBC);
    fPendikularraBC = -(1 / fMaldaBC);
    printf("   BC perp. = %.2lf\n", fPendikularraBC);

    // BC perpendikularren zuzenak duen desplazamendua
    SegmentuarenErdia(fBx, fBy, fCx, fCy, &fErdiaBCx, &fErdiaBCy);
    printf("   BC erdia = (%.2lf, %.2lf)\n", fErdiaBCx, fErdiaBCy);
    fDesplazamendu2 = fErdiaBCy + fErdiaBCx / fMaldaBC;
    printf("   Desplaz2 = %.2lf m\n\n", fDesplazamendu2);

    // Zentroa bi zuzen perpendikularren arteko ebakidura izango da
    // Zuzen z1:   m1 = fPerpendikularraAC | d1 = fDesplazamendu1
    // Zuzen z2:   m2 = fPerpendikularraBC | d2 = fDesplazamendu2

    // Zuzen z1:   fZy = m1·fZx + d1
    // Zuzen z2:   fZy = m2·fZx + d2

    // m1·fZx + d1 = m2·fZx + d2  ==>  fZx = (d1 - d2) / (-m1 + m2)
    //         fZy = m1·fZx + d1  ==>  fZy = m1·(d1 - d2) / (-m1 + m2) + d1

    // fZx = (d1 - d2) / (-m1 + m2)
    // fZy = (m2·d1 - m1·d2) / (-m1 + m2)
    ZentroaKalkulatu(fPendikularraAC, fPendikularraBC, fDesplazamendu1, fDesplazamendu2, &fZx, &fZy);

    printf("   Z zentr. = (%.2lf, %.2lf)\n\n", fZx, fZy);
    printf("   (x - fZx)^2 + (y - fZy)^2 - fR^2  <  0.000001\n");

    if (ErpinaZirkunferentzianDago(fZx, fZy, fR, fAx, fAy))
        printf("   (%.2lf, %.2lf) erpina zirkunferentzian dago\n", fAx, fAy);
    else
        printf("   Errorea A erpinean\n");

    if (ErpinaZirkunferentzianDago(fZx, fZy, fR, fBx, fBy))
        printf("   (%.2lf, %.2lf) erpina zirkunferentzian dago\n", fBx, fBy);
    else
        printf("   Errorea B erpinean\n");

    if (ErpinaZirkunferentzianDago(fZx, fZy, fR, fCx, fCy))
        printf("   (%.2lf, %.2lf) erpina zirkunferentzian dago\n", fCx, fCy);
    else
        printf("   Errorea C erpinean\n");

    return 0;
} 

Programaren balizko exekuzio bat hurrengo irudian erakusten da:

Eta hauxe kode osoa:

/* Ariketa-39_TriangeluarenZirkunzentroa: sarrerako eta irteerako parametroak */

// A puntua eta B puntua segmentu horizontal batean daude
// A puntua eta B puntua ez dira bat
// C puntua ez dago AB segmentu horizontalean
// AC segmentua ez da bertikala
// BC segmentua ez da bertikala

// 39. ariketa: A, B eta C erpinez triangelua definitu (6 koordenatu). 

//     AB aldea horizontala izango da eta ABC triangeluari dagokion    
//     zirkunferentzia zirkunskribatuaren R erradioa kalkulatu.        
//     ABC triangeluari dagokion zirkunferentzia zirkunskribatuaren Z  
//     zentroaren bi koordenatuak Zx eta Zy kalkulatu.                 

//     Datuak hiru erpinen koordenatuak dira eta prozedura batean      
//     hartzen dira, adibidez: (0.0, 0.0), (4.0, 0.0) eta (2.0, 2.0)   


#include <stdio.h>
#include <math.h>

// ErpinakEskuratu: irteerako 6 parametro
void ErpinakEskuratu(float *fAx, float *fAy, float *fBx, float *fBy, float *fCx, float *fCy);
// AldeaLortu: sarrerako 4 parametro, emaitza float
float AldeaLortu(float f1x, float f1y, float f2x, float f2y);
// AzaleraLortu: sarrerako 6 parametro, emaitza float
float AzaleraLortu(float fAx, float fAy, float fBx, float fBy, float fCx, float fCy);
// ErrradioaLortu: sarrerako 4 parametro, emaitza float
float ErrradioaLortu(float fA, float fB, float fC, float fS);
// ZuzenarenMalda: sarrerako 4 parametro, emaitza float
float ZuzenarenMalda(float fPx, float fPy, float fQx, float fQy);
// SegmentuarenErdia: sarrerako 4 parametro, irteerako 2 parametro
void SegmentuarenErdia(float fPx, float fPy,
                       float fQx, float fQy,
                       float *fErdiaPQx, float *fErdiaPQy);
// ZentroaKalkulatu: sarrerako 4 parametro, irteerako 2 parametro
void ZentroaKalkulatu(float fM1, float fM2, float fD1, float fD2, float *fZx, float *fZy);
// ErpinaZirkunferentzianDago: sarrerako 5 parametro, emaitza int
int ErpinaZirkunferentzianDago(float fZx, float fZy, float fR, float fAx, float fAy);


int main()
{
    float fAx, fAy, fBx, fBy, fCx, fCy, fZx, fZy;       // koordenatuak
    float fErdiaACx, fErdiaACy, fErdiaBCx, fErdiaBCy;   // koordenatuak
    float fA, fB, fC, fR, fS;                           // distantziak
    float fMaldaAC, fPendikularraAC;                    // maldak
    float fMaldaBC, fPendikularraBC;                    // maldak
    float fDesplazamendu1, fDesplazamendu2;             // distantziak

    printf("\n\n\n");

    // triangeluaren hiru erpinak irakurri
    ErpinakEskuratu(&fAx, &fAy, &fBx, &fBy, &fCx, &fCy);

    printf("\n");

    // triangeluaren hiru aldeak lortu
    fA = AldeaLortu(fBx, fBy, fCx, fCy);    // BC segmentuaren luzera lortu
    fB = AldeaLortu(fAx, fAy, fCx, fCy);    // AC segmentuaren luzera lortu
    fC = AldeaLortu(fAx, fAy, fBx, fBy);    // AB segmentuaren luzera lortu

    printf("   fA aldea = %.2lf m\n", fA);  // BC segmentuaren luzera erakutsi
    printf("   fB aldea = %.2lf m\n", fB);  // AC segmentuaren luzera erakutsi
    printf("   fC aldea = %.2lf m\n", fC);  // AB segmentuaren luzera erakutsi

    // triangeluaren azalera kalkulatu erpinak ezagunak izatean
    fS = AzaleraLortu(fAx, fAy, fBx, fBy, fCx, fCy);

    printf("   fS azal. = %.3lf m^2\n\n", fS);

    // erradioa kalkulatzeko formula: (fA·fB·fC)/(4·fS)
    fR = ErrradioaLortu(fA, fB, fC, fS);

    printf("   fR erra. = %.3lf m\n\n", fR);

    // AC perpendikularraren malda
    fMaldaAC = ZuzenarenMalda(fAx, fAy, fCx, fCy);
    printf("   AC malda = %.2lf\n", fMaldaAC);
    fPendikularraAC = -(1 / fMaldaAC);
    printf("   AC perp. = %.2lf\n", fPendikularraAC);

    // AC perpendikularren zuzenak duen desplazamendua
    SegmentuarenErdia(fAx, fAy, fCx, fCy, &fErdiaACx, &fErdiaACy);
    printf("   AC erdia = (%.2lf, %.2lf)\n", fErdiaACx, fErdiaACy);
    fDesplazamendu1 = fErdiaACy + fErdiaACx / fMaldaAC;
    printf("   Desplaz1 = %.2lf m\n\n", fDesplazamendu1);

    // BC perpendikularraren malda
    fMaldaBC = ZuzenarenMalda(fBx, fBy, fCx, fCy);
    printf("   BC malda = %.2lf\n", fMaldaBC);
    fPendikularraBC = -(1 / fMaldaBC);
    printf("   BC perp. = %.2lf\n", fPendikularraBC);

    // BC perpendikularren zuzenak duen desplazamendua
    SegmentuarenErdia(fBx, fBy, fCx, fCy, &fErdiaBCx, &fErdiaBCy);
    printf("   BC erdia = (%.2lf, %.2lf)\n", fErdiaBCx, fErdiaBCy);
    fDesplazamendu2 = fErdiaBCy + fErdiaBCx / fMaldaBC;
    printf("   Desplaz2 = %.2lf m\n\n", fDesplazamendu2);

    // Zentroa bi zuzen perpendikularren arteko ebakidura izango da
    // Zuzen z1:   m1 = fPerpendikularraAC | d1 = fDesplazamendu1
    // Zuzen z2:   m2 = fPerpendikularraBC | d2 = fDesplazamendu2

    // Zuzen z1:   fZy = m1·fZx + d1
    // Zuzen z2:   fZy = m2·fZx + d2

    // m1·fZx + d1 = m2·fZx + d2  ==>  fZx = (d1 - d2) / (-m1 + m2)
    //         fZy = m1·fZx + d1  ==>  fZy = m1·(d1 - d2) / (-m1 + m2) + d1

    // fZx = (d1 - d2) / (-m1 + m2)
    // fZy = (m2·d1 - m1·d2) / (-m1 + m2)
    ZentroaKalkulatu(fPendikularraAC, fPendikularraBC, fDesplazamendu1, fDesplazamendu2, &fZx, &fZy);

    printf("   Z zentr. = (%.2lf, %.2lf)\n\n", fZx, fZy);
    printf("   (x - fZx)^2 + (y - fZy)^2 - fR^2  <  0.000001\n");

    if (ErpinaZirkunferentzianDago(fZx, fZy, fR, fAx, fAy))
        printf("   (%.2lf, %.2lf) erpina zirkunferentzian dago\n", fAx, fAy);
    else
        printf("   Errorea A erpinean\n");

    if (ErpinaZirkunferentzianDago(fZx, fZy, fR, fBx, fBy))
        printf("   (%.2lf, %.2lf) erpina zirkunferentzian dago\n", fBx, fBy);
    else
        printf("   Errorea B erpinean\n");

    if (ErpinaZirkunferentzianDago(fZx, fZy, fR, fCx, fCy))
        printf("   (%.2lf, %.2lf) erpina zirkunferentzian dago\n", fCx, fCy);
    else
        printf("   Errorea C erpinean\n");

    return 0;
}

void ErpinakEskuratu(float *fAx, float *fAy, float *fBx, float *fBy, float *fCx, float *fCy)
{
    printf("   A erpinaren koordenatuak eman,\n");
    printf("   Ax koordenatua: ");
    scanf("%f", fAx);
    printf("   Ay koordenatua: ");
    scanf("%f", fAy);
    printf("\n");

    printf("   B erpinaren koordenatuak eman,\n");
    do
    {
        printf("   Bx koordenatua: ");
        scanf("%f", fBx);
        if (*fBx == *fAx)
            printf("   Ax koordenatua eta Bx koordenatua desberdinak izan behar dira...\n\a");
    } while (*fBx == *fAx);
    *fBy = *fAy;  // AB segmentu horizontala
    printf("   By koordenatua: %.2lf\n", *fBy);
    printf("\n");

    printf("   C erpinaren koordenatuak eman,\n");
    if (*fAx < *fBx)
    {
        do
        {
            printf("   Cx koordenatua: ");
            scanf("%f", fCx);
            if (*fCx <= *fAx || *fCx >= *fBx)
                printf("   Ax < Cx < Bx bete behar da...\n\a");
        } while (*fCx <= *fAx || *fCx >= *fBx); //  fAx < fCx < fBx
    }
    else
    {
        do
        {
            printf("   Cx koordenatua: ");
            scanf("%f", fCx);
            if (*fCx <= *fBx || *fCx >= *fAx)
                printf("   Bx < Cx < Ax bete behar da...\n\a");
        } while (*fCx <= *fBx || *fCx >= *fAx); //  fBx < fCx < fAx
    }
    do
    {
        printf("   Cy koordenatua: ");
        scanf("%f", fCy);
        if (*fCy == *fAy)
            printf("   C ezin da egon AB segmentuan...\n\a");
    } while (*fCy == *fAy); // C ez da AB segmentuan
}

float AldeaLortu(float f1x, float f1y, float f2x, float f2y)
{
    return sqrt(pow(f2x - f1x, 2) + pow(f2y - f1y, 2));
}

float AzaleraLortu(float fAx, float fAy, float fBx, float fBy, float fCx, float fCy)
{
    return fabs(0.5 * (fAx * fBy + fBx * fCy + fCx * fAy - fCx * fBy - fBx * fAy - fAx * fCy));
}

float ErrradioaLortu(float fA, float fB, float fC, float fS)
{
    return (fA * fB * fC) / (4 * fS);
}

float ZuzenarenMalda(float fPx, float fPy, float fQx, float fQy)
{
    return (fQy - fPy) / (fQx - fPx);
}

void SegmentuarenErdia(float fPx, float fPy,
                       float fQx, float fQy,
                       float *fErdiaPQx, float *fErdiaPQy)
{
    if (fPx >= fQx)
        *fErdiaPQx = fQx + fabs(fPx - fQx) / 2;
    else
        *fErdiaPQx = fPx + fabs(fPx - fQx) / 2;

    if (fPy <= fQy)
        *fErdiaPQy = fPy + fabs(fPy - fQy) / 2;
    else
        *fErdiaPQy = fQy + fabs(fPy - fQy) / 2;
}

void ZentroaKalkulatu(float fM1, float fM2, float fD1, float fD2, float *fZx, float *fZy)
{
    *fZx = (fD1 - fD2) / (-fM1 + fM2);
    *fZy = (fM2 * fD1 - fM1 * fD2) / (-fM1 + fM2);
}

int ErpinaZirkunferentzianDago(float fZx, float fZy, float fR, float fAx, float fAy)
{
    return (pow(fAx - fZx, 2) + pow(fAy - fZy, 2) - pow(fR, 2) < 0.000001);
}





  • Ariketa-39_TriangeluarenZirkunzentroa.cbp | main.c

 

iruzkinik ez:

Argitaratu iruzkina