1 package eu.mihosoft.vrl.v3d;
3 import java.util.ArrayList;
6 import javafx.scene.shape.ClosePath;
7 import javafx.scene.shape.CubicCurveTo;
8 import javafx.scene.shape.LineTo;
9 import javafx.scene.shape.MoveTo;
10 import javafx.scene.shape.Path;
11 import javafx.scene.shape.PathElement;
12 import javafx.scene.shape.QuadCurveTo;
13 import javafx.scene.shape.Rectangle;
14 import javafx.scene.shape.Shape;
15 import javafx.scene.text.Font;
16 import javafx.scene.text.Text;
17 import java.util.stream.Collectors;
18 import java.util.stream.IntStream;
19 import javafx.beans.property.DoubleProperty;
20 import javafx.beans.property.SimpleDoubleProperty;
21 import javafx.scene.paint.Color;
28 @SuppressWarnings(
"restriction")
30 private static final String default_font =
"FreeSerif";
31 private final static int POINTS_CURVE = 10;
36 private final List<LineSegment> polis =
new ArrayList<>();
37 ArrayList<CSG> sections =
new ArrayList<CSG>();
38 ArrayList<CSG> holes =
new ArrayList<CSG>();
52 private List<Vector3d> points;
55 private List<LineSegment> holes =
new ArrayList<>();
56 private String letter;
58 public LineSegment(String text) {
62 public String getLetter() {
66 public void setLetter(String letter) {
70 public boolean isHole() {
74 public void setHole(
boolean isHole) {
78 public List<Vector3d> getPoints() {
82 public void setPoints(List<Vector3d> points) {
86 public Path getPath() {
90 public void setPath(Path path) {
98 public void setOrigen(
Vector3d origen) {
102 public List<LineSegment> getHoles() {
106 public void setHoles(List<LineSegment> holes) {
110 public void addHole(LineSegment hole) {
115 public String toString() {
116 return "Poly{" +
"points=" + points +
", path=" + path +
", origen=" + origen +
", holes=" + holes +
'}';
122 throw new NumberFormatException(
"length can not be negative");
124 points =
new ArrayList<>();
126 Text textNode =
new Text(text);
127 textNode.setFont(font);
130 Path subtract = (Path) (Shape.subtract(textNode,
new Rectangle(0, 0)));
133 subtract.getElements().forEach(this::getPoints);
144 for (
int i = 0; i < sections.size(); i++) {
145 for (
CSG h : holes) {
147 if (sections.get(i).touching(h)) {
153 }
catch (Exception e) {
173 @SuppressWarnings(
"restriction")
174 public static ArrayList<
CSG> text(
double dir, String text, Font font) {
186 return polis.stream().sorted((p1,p2)->(
int)(p1.getOrigen().x-p2.getOrigen().x))
187 .map(LineSegment::getOrigen).collect(Collectors.toList());
191 if(elem instanceof MoveTo){
193 p0=
new Vector3d((
float)((MoveTo)elem).getX(),(
float)((MoveTo)elem).getY(),0f);
195 }
else if(elem instanceof LineTo){
196 points.add(
new Vector3d((
float)((LineTo)elem).getX(),(
float)((LineTo)elem).getY(),0f));
197 }
else if(elem instanceof CubicCurveTo){
198 Vector3d ini = (points.size()>0?points.get(points.size()-1):p0);
199 IntStream.rangeClosed(1, POINTS_CURVE).forEach(i->points.add(evalCubicBezier((CubicCurveTo)elem, ini, ((
double)i)/POINTS_CURVE)));
200 }
else if(elem instanceof QuadCurveTo){
201 Vector3d ini = (points.size()>0?points.get(points.size()-1):p0);
202 IntStream.rangeClosed(1, POINTS_CURVE).forEach(i->points.add(evalQuadBezier((QuadCurveTo)elem, ini, ((
double)i)/POINTS_CURVE)));
203 }
else if(elem instanceof ClosePath){
208 if(Math.abs(getArea())>0.001){
209 LineSegment line =
new LineSegment(text);
210 line.setHole(isHole());
211 line.setPoints(points);
212 line.setPath(generatePath());
223 points.remove(points.size() - 1);
229 sections.add(newLetter);
231 holes.add(newLetter);
233 points=
new ArrayList<>();
238 3*t*Math.pow(1-t,2)*c.getControlX1()+
239 3*(1-t)*t*t*c.getControlX2()+
240 Math.pow(t, 3)*c.getX()),
241 (
float)(Math.pow(1-t,3)*ini.
y+
242 3*t*Math.pow(1-t, 2)*c.getControlY1()+
243 3*(1-t)*t*t*c.getControlY2()+
244 Math.pow(t, 3)*c.getY()),
251 2*(1-t)*t*c.getControlX()+
252 Math.pow(t, 2)*c.getX()),
253 (
float)(Math.pow(1-t,2)*ini.
y+
254 2*(1-t)*t*c.getControlY()+
255 Math.pow(t, 2)*c.getY()),
261 DoubleProperty res=
new SimpleDoubleProperty();
262 IntStream.range(0, points.size()-1)
263 .forEach(i->res.set(res.get()+points.get(i).cross(points.get(i+1)).z));
266 return res.doubleValue()/2d;
276 Path path =
new Path(
new MoveTo(points.get(0).x,points.get(0).y));
277 points.stream().skip(1).forEach(p->path.getElements().add(
new LineTo(p.x,p.y)));
278 path.getElements().add(
new ClosePath());
279 path.setStroke(Color.GREEN);
281 path.setFill(Color.RED);
CSG difference(List< CSG > csgs)
static boolean isCCW(Polygon polygon)
static CSG points(Vector3d dir, List< Vector3d > points)
static Polygon fromPoints(List< Vector3d > points, PropertyStorage shared)
void getPoints(PathElement elem)
Vector3d evalQuadBezier(QuadCurveTo c, Vector3d ini, double t)
List< LineSegment > getLineSegment()
TextExtrude(String text, Font font, double dir)
List< Vector3d > getOffset()
Vector3d evalCubicBezier(CubicCurveTo c, Vector3d ini, double t)
static Vector3d y(double y)
static Vector3d x(double x)