/* @file SketchLinePath.java
*
* @author marco corvi
* @date jan 2013
*
* @brief TopoDroid 3d sketch: line-path (lines)
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Matrix;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Iterator;
// import java.util.List;
import java.util.ArrayList;
import android.util.Log;
/**
*/
public class SketchLinePath extends SketchPath
{
// boolean log;
boolean mClosed;
// boolean mReversed;
String mOptions;
Line3D mLine; // 3D points of the traced line (scene coords)
ArrayList< Vector > mPts3D; // points 3D for the triangulated surface
float mAngle; // rotation angle with respect to the centerline (used by makeSurface)
/**
* @param path_type path type (POINT, LINE, AREA)
* @param th_type therion type
* @param view_type view type (top, side, 3d)
* @param s1 first station
* @param s2 second station
* @param painter painter
*/
public SketchLinePath( int path_type, int th_type, String s1, String s2, SketchPainter painter )
{
super( path_type, s1, s2 );
// log = true;
// Log.v("DistoX", "line path " + s1 + "-" + s2 + " " + path_type + " Th " + th_type + " v " + view_type );
mThType = th_type;
mClosed = false;
// mReversed = false;
mOptions = null;
mLine = new Line3D();
mPts3D = new ArrayList< Vector >();
if ( path_type == DrawingPath.DRAWING_PATH_LINE ) {
mPaint = painter.greenPaint;
// mPaint = BrushManager.mLineLib.getSymbolPaint( mThType );
} else if ( path_type == DrawingPath.DRAWING_PATH_AREA ) {
// mPaint = painter.areaPaint;
mPaint = BrushManager.mAreaLib.getSymbolPaint( mThType );
} else {
mPaint = painter.whitePaint;
}
}
// (x,y,z) world (=scene) coords
Vector addLinePoint( float x, float y, float z )
{
Vector ret = new Vector(x,y,z);
mLine.points.add( ret );
return ret;
}
/** make the3D points for the triangulated surface
* @param cos_clino cosine(clino)
* @param vertical whether to use the "vertical" condition
* @param v1 first vector for the "vertical" condition
* @param v2 second vector for the "vertical" condition
*/
void make3dPoints( float cos_clino, boolean vertical, Vector v1, Vector v2 )
{
Vector dv = (v1 != null && v2 != null)? v2.minus(v1) : null;
mPts3D.clear();
float len = 0.0f; // compute the length of the 3D line
Vector p1 = mLine.points.get(0);
int n = mLine.points.size();
for ( int k=1; k<n; ++k ) {
Vector p2 = mLine.points.get(k);
len += p1.distance(p2);
p1 = p2;
}
// estimate number of points for the triangulated surface
// FIXME divide by cos(clino)
int np = (1 + (int)(len/(cos_clino * TDSetting.mSketchSideSize)) );
if ( np < SketchDef.POINT_MIN ) np = SketchDef.POINT_MIN;
// if ( np > SketchDef.POINT_MAX ) np = SketchDef.POINT_MAX;
float step = len / np;
len = 0.01f; // a bit (1 cm) beyond the point: this ensures that p(0) is added
p1 = mLine.points.get(0);
int kk = 0;
for ( int k=0; k<n; ++k ) {
Vector p2 = mLine.points.get(k);
len += p1.distance(p2);
p1 = p2;
if ( len > kk * step ) {
++ kk;
if ( ! vertical ) {
mPts3D.add( p1 );
} else {
// "vertical" condition: p projects on the line v1-v2 inside the segment [v1,v2]
// (p-v1).(v2-v1) >= 0 && (p-v2).(v1-v2) >= 0
Vector p1v1 = p1.minus( v1 );
Vector p1v2 = p1.minus( v2 );
if ( p1v1.dot( dv ) >= 0 && p1v2.dot( dv ) < 0 ) mPts3D.add( p1 );
}
}
}
// Log.v("DistoX", " make 3d pts " + mPts3D.size() );
}
void close()
{
mClosed = true;
}
// void addLinePoint3( float x1, float y1, float z1, float x2, float y2, float z2, float x, float y, float z, boolean last )
// {
// addLinePoint( x,y,z );
// }
// @Override
float distance( float x, float y, float z )
{
float dist = 1000f; // FIXME
for ( Vector pt : mLine.points ) {
float d = Math.abs( pt.x - x ) + Math.abs( pt.y - y ) + Math.abs( pt.z - z );
if ( d < dist ) dist = d;
}
return dist;
}
public void draw( Canvas canvas, Matrix matrix, Sketch3dInfo info )
{
Path path = new Path();
boolean first = true;
PointF q = new PointF();
for ( Vector p : mLine.points ) {
// project on (cos_clino*sin_azi, -cos_clino*cos_azimuth, -sin_clino)
info.worldToSceneOrigin( p.x, p.y, p.z, q );
if ( first ) {
path.moveTo( q.x, q.y );
first = false;
} else {
path.lineTo( q.x, q.y );
}
}
// if ( mClosed && mLine.points.size() > 2 ) { // FIXME SOON
// Vector p = mLine.points.get(0);
// info.worldToSceneOrigin( p.x, p.y, p.z, q );
// path.lineTo( q.x, q.y );
// }
path.transform( matrix );
canvas.drawPath( path, mPaint );
}
@Override
public String toTherion()
{
// Log.v("DistoX", "Line toTherion, stations " + st1 + " " + st2 );
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
if ( mType == DrawingPath.DRAWING_PATH_LINE ) {
pw.format("line %s %s -shot %s %s",
"3d", BrushManager.mLineLib.getSymbolThName(mThType), st1, st2 );
if ( mClosed ) {
pw.format(" -close on");
}
} else if ( mType == DrawingPath.DRAWING_PATH_AREA ) {
// area border is closed by default
pw.format("area %s %s -shot %s %s",
"3d", BrushManager.mAreaLib.getSymbolThName(mThType), st1, st2 );
}
if ( mOptions != null && mOptions.length() > 0 ) {
pw.format(" %s", mOptions );
}
pw.format("\n");
for ( Vector pt : mLine.points ) {
pt.toTherion( pw );
}
// if ( mThType == BrushManager.mLineLib.mLineSlopeIndex ) {
// pw.format(" l-size 40\n");
// }
if ( mType == DrawingPath.DRAWING_PATH_LINE ) {
pw.format("endline\n");
} else if ( mType == DrawingPath.DRAWING_PATH_AREA ) {
pw.format("endarea\n");
}
return sw.getBuffer().toString();
}
}