/*
* This file is part of LaTeXDraw.
* Copyright (c) 2005-2017 Arnaud BLOUIN
* LaTeXDraw is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
* LaTeXDraw is distributed without any warranty; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*/
package net.sf.latexdraw.view.pst;
import java.util.List;
import net.sf.latexdraw.models.MathUtils;
import net.sf.latexdraw.models.interfaces.shape.IFreehand;
import net.sf.latexdraw.models.interfaces.shape.IPoint;
import org.eclipse.jdt.annotation.NonNull;
/**
* Defines a PSTricks view of the LFreeHand model.
* @author Arnaud Blouin
*/
public class PSTFreeHandView extends PSTClassicalView<IFreehand> {
/**
* Creates and initialises a LFreeHand PSTricks view.
* @param model The model to view.
* @throws IllegalArgumentException If the given model is not valid.
* @since 3.0
*/
protected PSTFreeHandView(final @NonNull IFreehand model) {
super(model);
}
/**
* Updates the cache with the code of the freehand shape having the Curve style.
*/
protected void updateCacheCurve(final StringBuilder coord, final double originx, final double originy, final double ppc) {
final List<IPoint> pts = shape.getPoints();
int i;
final int size = shape.getNbPoints();
final int interval = shape.getInterval();
float prevx;
float prevy;
float curx = (float) pts.get(0).getX();
float cury = (float) pts.get(0).getY();
float midx = 0f;
float midy = 0f;
coord.append("\\moveto(").append(MathUtils.INST.getCutNumberFloat(((curx - originx) / ppc)));//$NON-NLS-1$
coord.append(',').append(MathUtils.INST.getCutNumberFloat((originy - cury) / ppc)).append(')').append('\n');
if(pts.size() > interval) {
prevx = curx;
prevy = cury;
curx = (float) pts.get(interval).getX();
cury = (float) pts.get(interval).getY();
midx = (curx + prevx) / 2.0f;
midy = (cury + prevy) / 2.0f;
coord.append("\\lineto(").append(MathUtils.INST.getCutNumberFloat(((midx - originx) / ppc)));//$NON-NLS-1$
coord.append(',').append(MathUtils.INST.getCutNumberFloat((originy - midy) / ppc)).append(')').append('\n');
}
for(i = interval * 2; i < size; i += interval) {
final float x1 = (midx + curx) / 2.0f;
final float y1 = (midy + cury) / 2.0f;
prevx = curx;
prevy = cury;
curx = (float) pts.get(i).getX();
cury = (float) pts.get(i).getY();
midx = (curx + prevx) / 2.0f;
midy = (cury + prevy) / 2.0f;
final float x2 = (prevx + midx) / 2.0f;
final float y2 = (prevy + midy) / 2.0f;
coord.append("\\curveto(").append(MathUtils.INST.getCutNumberFloat((x1 - originx) / ppc));//$NON-NLS-1$
coord.append(',').append(MathUtils.INST.getCutNumberFloat((originy - y1) / ppc)).append(')').append('(');
coord.append(MathUtils.INST.getCutNumberFloat((x2 - originx) / ppc)).append(',');
coord.append(MathUtils.INST.getCutNumberFloat((originy - y2) / ppc)).append(')').append('(');
coord.append(MathUtils.INST.getCutNumberFloat((midx - originx) / ppc)).append(',');
coord.append(MathUtils.INST.getCutNumberFloat((originy - midy) / ppc)).append(')').append('\n');
}
if(i - interval + 1 < size) {
final float x1 = (midx + curx) / 2.0f;
final float y1 = (midy + cury) / 2.0f;
prevx = curx;
prevy = cury;
curx = (float) pts.get(pts.size() - 1).getX();
cury = (float) pts.get(pts.size() - 1).getY();
midx = (curx + prevx) / 2.0f;
midy = (cury + prevy) / 2.0f;
final float x2 = (prevx + midx) / 2.0f;
final float y2 = (prevy + midy) / 2.0f;
coord.append("\\curveto("); //$NON-NLS-1$
coord.append(MathUtils.INST.getCutNumberFloat((x1 - originx) / ppc)).append(',');
coord.append(MathUtils.INST.getCutNumberFloat((originy - y1) / ppc)).append(')').append('(');
coord.append(MathUtils.INST.getCutNumberFloat((x2 - originx) / ppc)).append(',');
coord.append(MathUtils.INST.getCutNumberFloat((originy - y2) / ppc)).append(')').append('(');
coord.append(MathUtils.INST.getCutNumberFloat((pts.get(pts.size() - 1).getX() - originx) / ppc)).append(',');
coord.append(MathUtils.INST.getCutNumberFloat((originy - pts.get(pts.size() - 1).getY()) / ppc)).append(')').append('\n');
}
}
/**
* Updates the cache with the code of the freehand shape having the Line style.
*/
protected void updateCacheLines(final StringBuilder coord, final double originx, final double originy, final double ppc) {
final List<IPoint> pts = shape.getPoints();
IPoint p = pts.get(0);
int i;
final int size = shape.getNbPoints();
final int interval = shape.getInterval();
coord.append("\\moveto(").append(MathUtils.INST.getCutNumberFloat((p.getX() - originx) / ppc));//$NON-NLS-1$
coord.append(',').append(MathUtils.INST.getCutNumberFloat((originy - p.getY()) / ppc)).append(')').append('\n');
for(i = interval; i < size; i += interval) {
p = pts.get(i);
coord.append("\\lineto(").append(MathUtils.INST.getCutNumberFloat((p.getX() - originx) / ppc));//$NON-NLS-1$
coord.append(',').append(MathUtils.INST.getCutNumberFloat((originy - p.getY()) / ppc)).append(')').append('\n');
}
if(i - interval < size)
coord.append("\\lineto(").append(MathUtils.INST.getCutNumberFloat((pts.get(pts.size() - 1).getX() - originx) / ppc)).append(//$NON-NLS-1$
',').append(MathUtils.INST.getCutNumberFloat((originy - pts.get(pts.size() - 1).getY()) / ppc)).append(')').append('\n');
}
@Override
public String getCode(final IPoint origin, final float ppc) {
if(!MathUtils.INST.isValidPt(origin) || ppc < 1 || shape.getNbPoints() < 2) return "";
final StringBuilder coord = new StringBuilder();
final StringBuilder rot = getRotationHeaderCode(ppc, origin);
final StringBuilder code = new StringBuilder();
switch(shape.getType()) {
case CURVES:
updateCacheCurve(coord, origin.getX(), origin.getY(), ppc);
break;
case LINES:
updateCacheLines(coord, origin.getX(), origin.getY(), ppc);
break;
}
if(rot != null) code.append(rot);
code.append("\\pscustom[");//$NON-NLS-1$
code.append(getPropertiesCode(ppc));
code.append("]\n{\n\\newpath\n");//$NON-NLS-1$
code.append(coord);
code.append(shape.isOpen() ? "" : "\\closepath");//$NON-NLS-1$//$NON-NLS-2$
code.append(shape.hasShadow() ? "\\openshadow\n" : "");//$NON-NLS-1$//$NON-NLS-2$
code.append('}');
if(rot != null) code.append('}');
return code.toString();
}
}