JavaFX - Jak jednoduše rozdělit shape?
Dobrý den,
Pomocí tohoto kódu vytvořím Path
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.*;
import javafx.stage.Stage;
public class DivideShape extends javafx.application.Application {
@Override
public void start(Stage primaryStage) {
var path = new Path(new MoveTo(200, 380), new LineTo(0, 300),
new ArcTo(300, 300, 0, 300, 0, false, true), new LineTo(380,
200), new ArcTo(180, 180, 0, 200, 380, false, false));
path.setFill(Color.BLUE);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(new Scene(new Pane(path)));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Ten potřebuji rozdělit na 5 částí (na 5 samostatných Path), tak jsem vytvořil 5 objektů, tvořící dohromady objekt výše.
@Override
public void start(Stage primaryStage) {
var path2 = new Path(new MoveTo(200, 380), new LineTo(0, 300),
new ArcTo(300, 300, 0, 300, 0, false, true), new LineTo(380,
200), new ArcTo(180, 180, 0, 200, 380, false, false));*/
var pane = new Pane();
var moveTo = new MoveTo(200, 380);
var lineTo = new LineTo(0, 300);
var arc_big = 300;
var arc_small = 180;
for (var deg = 198; deg <= 270; deg += 18) {
var path = new Path(moveTo, lineTo);
lineTo = new LineTo(300 + arc_big * Math.cos(Math.toRadians(deg)), 300 + arc_big * Math.sin(Math.toRadians(deg)));
path.getElements().add(new ArcTo(arc_big, arc_big, 0, lineTo.getX(), lineTo.getY(), false, true));
var move = new MoveTo(380 + arc_small * Math.cos(Math.toRadians(deg)), 380 + arc_small * Math.sin(Math.toRadians(deg)));
path.getElements().addAll(new LineTo(move.getX(), move.getY()),
new ArcTo(arc_small, arc_small, 0, moveTo.getX(), moveTo.getY(), false, false));
moveTo = move;
path.setFill(Color.color(Math.random(), Math.random(), Math.random()));
pane.getChildren().add(path);
}
primaryStage.setTitle("Hello World!");
primaryStage.setScene(new Scene(pane));
primaryStage.show();
}
Kód sice funguje, ale je příliš složitý. Navíc, i když jsem tento kód vytvořil, přesto jsem si po necelém měsíci nepamatoval, jak vlastně funguje.
Šlo by to, prosím Vás, nějak zjednodušit?
Děkuji
PS. Ještě mě napadla možnost to skutečně rozdělit na 5 částí, ale asi to nepůjde respektive nikde jsem nenašel zmínku o tom, že by něco takového bylo možné provést.
Tak on by ten kód byl o dost přehlednější, kdybys neprogramoval stylem copy+paste.
Math.toRadians(deg) - je tam 4x
Math.cos(...), Math.sin(...) - je tam obojí 2x
Pojmenování proměnných by taky mohlo být lepší. A mohl bys jich používat víc, čímž by se ten kód rozpadl na menší a srozumitelnější části. Používat výpočty v konstruktoru nebo obecně při volání metod na přehlednosti moc nepřidá.
A opravdu chceš, aby to vypadalo takhle? Vnitřní oblouk je čtvrtkruh, ale vnější ne.
Ano, vím, ale takhle to skutečně chci.
Omlouvám se, jak jsem to přepisoval do příkladu, tak jsem někde napsal hotové hodnoty
1. Na začátku vím pouze lineTo a moveToStart a oblouky z nich vypočítám
2. To samé i 300 a 380 v cyklu. To je ve skutečnosti taky jenom lineTo.getY() a moveToStart.getY()
A s těmi úhly máte pravdu. Jenže když to upravím, tak vznikne
kód neříkající absolutně nic. Ano, mohlo být více proměnných včetně jejich správného pojmenování.
Ale bez komentářů stejně nebude dávat smysl, jak algoritmus vlastně funguje.
Proto jsem chtěl, prosím Vás, vědět, jestli by to bylo možné nějak zjednodušit, případně použít jiný algoritmus?
Když tam bude víc správně pojmenovaných proměnných, tak to smysl dávat bude. Nezavrhuj to, dokud to nezkusíš.
Ano, správný počet a pojmenování proměnných může vysvětlit hodně, ale rozhodně ne všechno.
Nezavrhuji to, ale nevím, jak upravit kód výše, aby dával smysl bez nutnosti psát hromadu komentářů.
Např. že se používá sinova věta, z proměnných nezjistíte.
Že se tam používá sinová věta, jsem si teda opravdu nevšiml. Kde že tam je?
Právě pomocí pravoúhlého trojúhelníku jsem chtěl vypočítat souřadnice. A výpočet jsem dělal právě pomocí sinovi věty respektive základem byla sinova věta.
a / b = sin a / sin b
Avšak, pokud b bude přepona (poloměr kruhu) a protilehlý úhel je 90°, což je v případě sin 1, lze to upravit na
a = b * sin a
což je v podstatě to samé jako např. arc_big * sin v kódu výše.
Avšak, jak jsem se dopracoval k tomu, že je nutné přičíst hodnotu, navíc u souřadnice x nepoužít sin, ale cos a to zabalit do cyklu začínají 198°, to vážně nevím.
A jsme tam, o čem jsem mluvil. Vymyslel jsem algoritmus, který není jednoduchý a jelikož jsem si k němu nic nenapsal, tak ani nevím, jak vlastně funguje.
Jenže ty tam pravý úhel nemáš, takže se mi zdá, že jsi dvěma špatnými úvahami čistě náhodou trefil na správnou.
Nemám tady žádné IDE pro Javu, takže jsem to psal naslepo a bez vyzkoušení, ale napsal bych to asi takhle:
Mělo by to dělat přesně to, co tvůj kód, ale o dost přehledněji.
Moc se omlouvám za pozdní odpověď. Děkuji, Váš kód je dobrý, nicméně řešil jsem stejný problém na StackOverflow a poradil mi tento kód.
I když se kód jeví jednoduše, nepřišel jsem na to, jak upravit hodnoty, abych dosáhl stejného výsledku. Nejde mi o velikost okna, pouze aby byl oblouk vypadal stejně a dotýkal se levé a horní strany.
Na moji otázku, jak mám hodnoty zadat, mi odpověděl tímhle obrázkem, s fieldy
a že musím kód správně pochopit.
Jenže, jak jsem řekl, i když se kód jeví jednoduše, nepřišel jsem na to, jak hodnoty správně zadat.
Prosím o radu.
Děkuji
Jenže tenhle kód dělá něco jiného, i když trochu podobného. Takže požadovaného výsledku nedosáhneš žádnou úpravou parametrů.
Aha. Tak to je ten problém. A nelze dosáhnout aspoň podobného výsledku? např. aby oblouky tvořily část kružnice a ne elipsy.
A proč chceš dosahovat podobného výsledku, když ten můj kód dělá přesný výsledek?
Vlastně ano, takže tím bych to uzavřel. Děkuji
Tak jsem si to přepsal do JS + SVG (kód je ale i tak velice podobný) a takový je výsledek:
https://jsfiddle.net/0p6375z2/
Děkuji, ale tímhle způsobem to dělat nechci.