čtvrtek 26. května 2011

Body pod úsečkou

Zadání

Náhodným způsobem vygenerujte n dvojic reálných čísel v rozsahu 0 až 99.99. Tyto dvojice považujte za kartézské souřadnice bodů v rovině. Dále vygenerujte další dvojici náhodných reálných čísel v rozsahu 50 až 99.9, která povazujte za souřadnice koncových bodů úsečky na vodorovné a svislé ose. Vytiskněte všechny body, které leží v oblasti omezené touto úsečkou a osami.

VSTUP: n – počet bodů – dvojic souřadnic
VÝSTUP: Souřadnice všech bodů, které leží v dané oblasti.



Teorie

Vygenerování bodů nám zajistí objekt typu Random a jeho metoda nextDouble(). Pomocí této metody získámě desetinné číslo mezi nulou a jedničkou, proto ho budeme muset vynásobit 100, abychom získali číslo mezi nulou a stovkou. Takové číslo ovšem stále bude ve tvaru s příliš mnoha desetinnými místy, proto si vytvoříme metodu, jež nám toto číslo zaokrouhlí na dvě desetinná místa (metoda Math.round() zaokrouhluje na celá čísla, proto je pro naše účely sama o sobě nevhodná).

Dále budeme potřebovat znát obecnou rovnici přímky:
a*x + b*y + c = 0
V našem případě bude a i b z intervalu <50;100> a c = -(a * b)

Určení, zda leží bod přímkou, uděláme srovnáním souřadnice y na přímce se souřadnicí y bodu.

Řešení

Začneme načtením počtu bodů a vytvořením dvourozměrného pole, do kterého tyto body budeme ukládat:

Scanner sc = new Scanner(System.in);
System.out.println("Zadejte počet bodů:");
int pointCount = sc.nextInt();
double[][] points = new double[pointCount][2];

Následně vygenerujeme požadovaný počet bodů, jejichž obě souřadnice uložíme do pole:

System.out.println("Výpis vygenerovaných bodů:");
Random r = new Random();
for(int i = 0; i < pointCount; i++){
    points[i][0] = roundTo(r.nextDouble() * 100, 2);
    points[i][1] = roundTo(r.nextDouble() * 100, 2);
    System.out.println("[" + points[i][0] + "][" + points[i][1] + "]");
}
System.out.println();

Pro zaokrouhlení na dvě desetinná místa používáme metodu roundTo(double číslo, int početDesetinnýchMíst), která vypadá následovně:

public static double roundTo(double a, int round){
    return Math.round(a * Math.pow(10, round)) / Math.pow(10, round);
}

Nejprve předané číslo vynásobíme 10^round a výsledek zaokoruhlíme - tím se zbavíme všech čísel za desetinnou řádkou. Následně toto číslo vydělíme 10^round, takže se vrátíme do desetinného tvaru, ale díky předchozímu zaokrouhlení budeme mít jen 2 desetinná místa.

Poté vygenerujeme parametry a, b přímky, proces bude téměř stejný jako u bodů, jen si přičtením 50 zajistíme, že vygenerované číslo bude nejméně 50.

double[] u = new double[3];
u[0] = roundTo(r.nextDouble() * 50 + 50, 2);
u[1] = roundTo(r.nextDouble() * 50 + 50, 2);
u[2] = -(u[0] * u[1]);
System.out.println("Tvar úsečky: " + u[0] + "*x + " + u[1] + "*y " + u[2]);

Zbývá již jen projít všechny body a srovnat souřadnice y bodu na přímce s bodem vygenerovaným na začátku:

System.out.println("Výpis bodů pod úsečkou:");
for(int i = 0; i < pointCount; i++){
    double y = (u[0] * points[i][0] + u[2]) / (-u[1]);
    if(y >= points[i][1]) 
        System.out.println("[" + points[i][0] + "][" + points[i][1] + "]");
}

A to je zatím vše, časem bych mohl tyto body společně s úsečkou ještě vykreslit ve zvláštním okně, ale to možná později.

Žádné komentáře:

Okomentovat