/** @file SketchModel.java
*
* @author marco corvi
* @date feb 2013
*
* @brief TopoDroid 3d sketch: sketch 3D model
* --------------------------------------------------------
* Copyright This sowftare is distributed under GPL-3.0 or later
* See the file COPYING.
* --------------------------------------------------------
*/
package com.topodroid.DistoX;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Collections;
import java.util.Locale;
import java.io.BufferedWriter;
import java.io.StringWriter;
import java.io.PrintWriter;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import android.graphics.Matrix;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.RectF;
import android.graphics.PointF;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.util.Log;
class SketchModel
{
private static final float mCloseness = TDSetting.mCloseness;
DistoXNum mNum;
Sketch3dInfo mInfo;
SketchPainter mPainter;
SketchSurface mCurrentSurface;
Matrix mMatrix;
List< NumStation > stations;
// List< NumShot > shots;
// List< NumSplay > splays;
List< SketchPath > mPaths;
private List<SketchFixedPath> mFixedStack;
private List<SketchStationName> mStations;
// private List<SketchSectionSet> mSectionSets;
List<SketchSurface> mSurfaces;
List<SketchSurface> mJoins;
ArrayList< SketchRefinement > mRefines;
ArrayList< Vector > mBorder3d;
// SketchLinePath mEditLine;
// ArrayList< PointF > mBorder;
SketchUndo mUndo;
SketchUndo mRedo;
int mDisplayMode = SketchDef.DISPLAY_NGBH;
int mActivityMode = SketchDef.MODE_MOVE;
public static final int highlightColor = 0xffff9999;
int cnt;
private float pi4 = (float)(Math.PI/4);
private float pi2 = pi4 * 2;
private Selection mSelection;
private SelectionSet mSelected;
SketchModel( Sketch3dInfo info, DistoXNum num, SketchPainter painter )
{
mInfo = info;
mPainter = painter;
mCurrentSurface = null;
setNum( num );
mPaths = Collections.synchronizedList( new ArrayList< SketchPath >() );
// points = Collections.synchronizedList( new ArrayList< SketchPointPath >() );
mFixedStack = Collections.synchronizedList(new ArrayList<SketchFixedPath>());
mStations = Collections.synchronizedList(new ArrayList<SketchStationName>());
mSurfaces = Collections.synchronizedList(new ArrayList<SketchSurface>());
mJoins = Collections.synchronizedList(new ArrayList<SketchSurface>());
// mSectionSets = Collections.synchronizedList( new ArrayList<SketchSectionSet>() );
mMatrix = new Matrix();
// mSectionBaseVector = null;
cnt = 0;
mUndo = null;
mRedo = null;
mSelection = new Selection();
mSelected = new SelectionSet();
mRefines = null;
// mEditLine = null;
// mBorder = null;
mBorder3d = null;
}
void setRefinement( ArrayList< SketchRefinement > refines ) { mRefines = refines; }
// void setEditLine( SketchLinePath line ) { mEditLine = line; }
// void setBorder( ArrayList< PointF > border ) { mBorder = border; }
int doRefinement( )
{
if ( mRefines == null || mRefines.size() == 0 ) return 0;
int ret = 0;
ArrayList< PointF > border = new ArrayList< PointF >();
mBorder3d = new ArrayList< Vector >();
synchronized( mRefines ) {
PointF p = new PointF(0,0);
mInfo.worldToSceneOrigin( mRefines.get(0).v2, p );
border.add( p );
for ( SketchRefinement ref : mRefines ) {
p = new PointF(0,0);
mBorder3d.add( ref.v3 );
mInfo.worldToSceneOrigin( ref.v3, p );
border.add( p );
}
for ( SketchRefinement ref : mRefines ) {
refineTriangleAtVertex( ref.t, ref.v, ref.v2, ref.v3 );
}
ret = findTrianglesInside( border );
}
return ret;
}
boolean joinSurfacesAtStation( SketchStationName st )
{
String name = st.mName;
Log.v("DistoX", "join surfaces at station " + name );
// for ( SketchSurface surface : mJoins ) {
// if ( surface.st1.equals( name ) ) {
// mJoins.remove( surface );
// break;
// }
// }
// SketchSectionSet sections = getSectionsAt ( name );
// Vector center = new Vector( st.x, st.y, st.z );
// return createJoinSurface( sections, name, center );
// TODO JOIN SURFACE(S)
return true;
}
/**
* @param sections station sections
* @param name station name
*/
// private boolean createJoinSurface( SketchSectionSet sections, String name, Vector center )
// {
// // Log.v("DistoX", "join sections nr: " + sections.size() );
// if ( sections.size() < 2 ) { // FIXME more than 2
// return false;
// }
// // Vector n0 = sections.getSection(0).getNormal();
// // Vector n1 = sections.getSection(1).getNormal();
// // if ( n1.dot(n0) < 0.0f ) {
// // sections.getSection(1).reverseLine();
// // }
// ArrayList< SketchFixedPath > splays1 = new ArrayList< SketchFixedPath >();
// if ( TopoDroidApp.mSketchUsesSplays ) {
// for ( SketchFixedPath p : mFixedStack ) {
// if ( p.mType == DrawingPath.DRAWING_PATH_SPLAY ) {
// if ( p.st1.equals( name ) ) {
// splays1.add( p );
// }
// }
// }
// // Log.v("DistoX", "make surface, ns " + ns + " splays " + splays1.size() + " " + splays2.size() );
// }
// SketchSurface surface = new SketchSurface( mInfo.st1, mInfo.st2, mPainter );
// surface.makeJoinTriangles( sections, mInfo, splays1, center );
// mJoins.add( surface );
// return true;
// }
// ------------------------------------------------------------------
void setLabelToLastPoint( String label )
{
int np = mPaths.size();
if ( np == 0 ) return;
SketchPath path = mPaths.get( np - 1 );
if ( path.mType != DrawingPath.DRAWING_PATH_POINT ) return;
SketchPointPath point = (SketchPointPath)path;
point.mLabel = label;
}
void setNum( DistoXNum num )
{
mNum = num;
stations = num.getStations();
// shots = num.getShots();
// splays = num.getSplays();
}
/** called from SketchWindow
* only 3D lines can be highlighted
*/
// void highlightLineRegion( )
// {
// int np = mPaths.size();
// if ( np == 0 ) return;
// SketchPath path = mPaths.get( np - 1 );
// if ( path.mType != DrawingPath.DRAWING_PATH_LINE) return;
// if ( mCurrentSurface == null || path.mSurface != mCurrentSurface ) return;
// mCurrentSurface.computeInnerBorder( (SketchLinePath)path, mInfo );
// }
void makeCut( )
{
if ( mCurrentSurface != null ) mCurrentSurface.makeCut();
}
// void makeExtrude( ArrayList<Vector> pts )
// {
// if ( mBorder3d == null ) return;
// if ( mCurrentSurface != null ) mCurrentSurface.makeExtrude( pts, mBorder3d );
// mBorder3d = null;
// }
void makeStretch( ArrayList<Vector> pts )
{
if ( mBorder3d == null ) return;
if ( mCurrentSurface != null ) mCurrentSurface.makeStretch( pts, mBorder3d );
mBorder3d = null;
}
void removeSurface( boolean with_sections )
{
if ( mCurrentSurface != null /* && mCurrentSurface.st1.equals( mInfo.station1 ) && mCurrentSurface.st2.equals( mInfo.station2 ) */ ) {
if ( with_sections ) {
// remove joins at the endpoints:
if ( mJoins != null ) {
synchronized( mJoins ) {
final Iterator i = mJoins.iterator();
while ( i.hasNext() ) {
final SketchSurface surface = (SketchSurface) i.next();
if ( mInfo.isConnectedTo(mCurrentSurface, SketchDef.DISPLAY_NGBH ) ) {
mJoins.remove( surface );
}
}
}
}
// clearSections();
}
if ( mPaths != null) {
synchronized( mPaths ) {
final Iterator i = mPaths.iterator();
while ( i.hasNext() ) {
final SketchPath path = (SketchPath) i.next();
if ( path.mSurface == mCurrentSurface ) {
mPaths.remove( path );
}
}
// mRedoStack.add( path );
}
}
mSurfaces.remove( mCurrentSurface );
}
mCurrentSurface = null;
}
void addPoint( SketchPointPath point )
{
// points.add( point );
mPaths.add( point );
point.mSurface = mCurrentSurface;
mUndo = new SketchUndo( mUndo, point );
mRedo = null;
}
// array of canvas 2d points
int findTrianglesInside( ArrayList<PointF> border )
{
return ( mCurrentSurface == null )? 0 : mCurrentSurface.findTrianglesInside( border );
}
int refineToMaxSide( float max_size )
{
return ( mCurrentSurface == null )? 0 : mCurrentSurface.refineToMaxSide( max_size );
}
void refineSurfaceAtCenters()
{
if ( mCurrentSurface != null ) mCurrentSurface.refineAtCenters();
}
void refineSurfaceAtSides()
{
if ( mCurrentSurface != null ) mCurrentSurface.refineAtSides();
}
boolean refineTriangleAtVertex( SketchTriangle t, SketchVertex v, float t1, float t2, boolean add )
{
return mCurrentSurface != null && mCurrentSurface.refineTriangleAtVertex( t, v, t1, t1, add );
}
boolean refineTriangleAtVertex( SketchTriangle t, SketchVertex vv, Vector v12, Vector v13 )
{
return mCurrentSurface != null && mCurrentSurface.refineTriangleAtVertex( t, vv, v12, v13, mInfo );
}
// boolean removeTriangle( SketchTriangle t )
// {
// return mCurrentSurface != null && mCurrentSurface.removeTriangle( t );
// }
void makeConvexSurface()
{
NumStation st1 = mInfo.station1;
NumStation st2 = mInfo.station2;
List<NumSplay> splay1 = mNum.getSplaysAt( st1 );
List<NumSplay> splay2 = mNum.getSplaysAt( st2 );
// Log.v("DistoX", "splays at 1: " + splay1.size() + " at 2: " + splay2.size() );
if ( splay1.size() < 2 || splay2.size() < 2 ) {
TDLog.Error( "makeConvexSurface too few spalys " + splay1.size() + " " + splay2.size() );
return;
}
ArrayList< Vector > pts = new ArrayList<Vector>();
for ( NumSplay sp : splay1 ) {
pts.add( sp.toVector() );
}
for ( NumSplay sp : splay2 ) {
pts.add( sp.toVector() );
}
Vector v1 = st1.toVector();
Vector v2 = st2.toVector();
ConvexHull hull = new ConvexHull( v1, v2, pts );
mCurrentSurface = new SketchSurface( mInfo.st1, mInfo.st2, mPainter );
mCurrentSurface.makeTriangles( mInfo, hull );
mSurfaces.add( mCurrentSurface );
}
void clearReferences()
{
synchronized( mFixedStack ) {
mFixedStack.clear();
}
synchronized( mStations ) {
mStations.clear();
}
}
void addSketchPath( SketchPath path )
{
mPaths.add( path );
path.mSurface = mCurrentSurface;
mUndo = new SketchUndo( mUndo, path );
mRedo = null;
}
public void addFixedPath( SketchFixedPath path )
{
mFixedStack.add( path );
}
public void addFixedStation( SketchStationName st )
{
mStations.add( st );
}
public void redo()
{
if ( mRedo != null ) {
SketchUndo redo = mRedo;
mRedo = mRedo.mNext;
switch ( redo.mType ) {
case SketchUndo.UNDO_PATH:
mPaths.add( redo.mPath );
break;
}
redo.mNext = mUndo;
mUndo = redo;
}
}
public void undo ()
{
if ( mUndo != null ) {
SketchUndo undo = mUndo;
mUndo = mUndo.mNext;
switch ( undo.mType ) {
case SketchUndo.UNDO_PATH:
int len = mPaths.size();
if ( len > 0) {
SketchPath path = mPaths.get( len-1 );
// if ( path == undo.mPath ) {
mPaths.remove( len-1 );
// }
}
// mPaths.remove( undo.mPath );
break;
}
undo.mNext = mRedo;
mRedo = undo;
}
}
public void setTransform( float dx, float dy, float s )
{
mMatrix = new Matrix();
mMatrix.postTranslate( dx, dy );
mMatrix.postScale( s, s );
}
public void executeAll( Canvas canvas, Handler doneHandler )
{
if ( mFixedStack != null ) {
synchronized( mFixedStack ) {
final Iterator i = mFixedStack.iterator();
while ( i.hasNext() ) {
final SketchFixedPath fixed = (SketchFixedPath) i.next();
if ( mInfo.isConnectedTo(fixed, mDisplayMode) ) {
fixed.draw( canvas, mMatrix, mInfo, mActivityMode );
}
//doneHandler.sendEmptyMessage(1);
}
}
}
// FIXME TODO draw for VIEW_3D
if ( mStations != null ) {
synchronized( mStations ) {
for ( SketchStationName st : mStations ) {
// if ( mInfo.contains( st.mName ) ) {
st.draw( canvas, mMatrix, mInfo );
// }
}
}
}
if ( mSurfaces != null ) {
synchronized( mSurfaces ) {
final Iterator i = mSurfaces.iterator();
while ( i.hasNext() ) {
final SketchSurface surface = (SketchSurface) i.next();
if ( mInfo.isConnectedTo(surface, mDisplayMode) ) {
surface.draw( canvas, mMatrix, mInfo, mActivityMode );
}
}
}
}
if ( mRefines != null && mRefines.size() > 0 ) {
synchronized( mRefines ) {
Path path = new Path();
PointF p = new PointF(0,0);
mInfo.worldToSceneOrigin( mRefines.get(mRefines.size()-1).v3, p );
path.moveTo( p.x, p.y );
for ( SketchRefinement ref : mRefines ) {
mInfo.worldToSceneOrigin( ref.v3, p );
path.lineTo( p.x, p.y );
}
// path.close();
path.transform( mMatrix );
canvas.drawPath( path, mPainter.bluePaint );
}
}
if ( mJoins != null ) {
synchronized( mJoins ) {
final Iterator i = mJoins.iterator();
while ( i.hasNext() ) {
final SketchSurface surface = (SketchSurface) i.next();
if ( mInfo.isConnectedTo(surface, mDisplayMode) ) {
surface.draw( canvas, mMatrix, mInfo, mActivityMode );
}
}
}
}
if ( mPaths != null ) {
synchronized( mPaths ) {
final Iterator i = mPaths.iterator();
while ( i.hasNext() ) {
final SketchPath path = (SketchPath) i.next();
if ( path.mType == DrawingPath.DRAWING_PATH_LINE || path.mType == DrawingPath.DRAWING_PATH_AREA ) {
SketchLinePath line = ( SketchLinePath ) path;
if ( mInfo.isConnectedTo(line, mDisplayMode) ) {
line.draw( canvas, mMatrix, mInfo );
}
} else if ( path.mType == DrawingPath.DRAWING_PATH_POINT ) {
SketchPointPath point = (SketchPointPath) path;
if ( mInfo.isConnectedTo(point, mDisplayMode) ) {
point.draw( canvas, mMatrix, mInfo );
}
}
}
}
}
// synchronized( points ) {
// final Iterator i = points.iterator();
// while ( i.hasNext() ) {
// final SketchPointPath point = (SketchPointPath) i.next();
// if ( mInfo.isConnectedTo(point, mDisplayMode) ) {
// point.draw( canvas, mMatrix, mInfo );
// }
// }
// }
// if ( mSectionBaseVector != null ) {
// synchronized( mSectionBaseVector ) {
// if ( mSectionType != SketchSection.SECTION_NONE ) {
// PointF q0 = new PointF();
// PointF q1 = new PointF();
// PointF q3 = new PointF();
// mInfo.worldToSceneOrigin( mSectionBaseVector.x, mSectionBaseVector.y, mSectionBaseVector.z, q0 );
// if ( mSectionType == SketchSection.SECTION_VERT ) {
// mInfo.worldToSceneOrigin( mSectionBaseVector.x-mInfo.ns, mSectionBaseVector.y+mInfo.ne, mSectionBaseVector.z, q1 );
// mInfo.worldToSceneOrigin( mSectionBaseVector.x, mSectionBaseVector.y, mSectionBaseVector.z-1, q3 );
// } else if ( mSectionType == SketchSection.SECTION_HORIZ ) {
// mInfo.worldToSceneOrigin( mSectionBaseVector.x+1, mSectionBaseVector.y, mSectionBaseVector.z, q1 );
// mInfo.worldToSceneOrigin( mSectionBaseVector.x, mSectionBaseVector.y+1, mSectionBaseVector.z, q3 );
// }
// Path path1 = new Path();
// Path path2 = new Path();
// path1.moveTo(q0.x, q0.y);
// path1.lineTo(q1.x, q1.y);
// path2.moveTo(q0.x, q0.y);
// path2.lineTo(q3.x, q3.y);
// path1.transform( mMatrix );
// path2.transform( mMatrix );
// canvas.drawPath( path1, mPainter.greenPaint ); // green = horiz/east
// canvas.drawPath( path2, mPainter.bluePaint ); // blue = vert/north
// // Log.v("DistoX", "draw base vector at " + q.x + " " + q.y );
// }
// }
// }
// synchronized( mSectionSets ) {
// final Iterator i = mSectionSets.iterator();
// while ( i.hasNext() ) {
// final SketchSectionSet s = (SketchSectionSet) i.next();
// if ( s.mFrom == mInfo.station1 && s.mTo == mInfo.station2 ) {
// // draw all sections of the set
// int ns = s.size();
// for ( int n = 0; n < ns; ++n ) {
// s.getSection(n).draw( canvas, mMatrix, mInfo, mPainter.bluePaint );
// }
// break;
// }
// }
// }
}
public SketchTriangle selectTriangleAt( float x_scene, float y_scene, SketchTriangle tri )
{
if ( tri != null ) {
// try tri first and its ngbhs
SketchSurface sfc = tri.surface;
tri = sfc.selectTriangleAt( x_scene, y_scene, mInfo, tri );
// sfc.mSelectedTriangle = tri;
}
if ( tri == null ) {
for ( SketchSurface surface : mSurfaces ) {
if ( surface.isSameShotAs( mInfo ) ) {
tri = surface.selectTriangleAt( x_scene, y_scene, mInfo, null );
// surface.mSelectedTriangle = tri;
if ( tri != null ) return tri;
}
}
}
return null;
}
public SketchFixedPath selectShotAt( float x, float y ) // (x,y) scene coords, view-mode
{
float min_dist = SketchDef.MIN_DISTANCE;
SketchFixedPath ret = null;
for ( SketchFixedPath p : mFixedStack ) {
if ( p.mType == DrawingPath.DRAWING_PATH_FIXED ) {
float d = p.distance( x, y );
if ( d < mCloseness && d < min_dist ) {
min_dist = d;
ret = p;
}
}
}
return ret;
}
public SketchLinePath selectLineAt( float x, float y, float z, int v ) // (x,y,z) world coords, view-mode
{
float min_dist = SketchDef.MIN_DISTANCE;
SketchLinePath ret = null;
for ( SketchPath p0 : mPaths ) {
if ( p0.mType == DrawingPath.DRAWING_PATH_LINE ) {
SketchLinePath p = (SketchLinePath)p0;
float d = p.distance( x, y, z );
if ( d < mCloseness && d < min_dist ) {
min_dist = d;
ret = p;
}
}
}
return ret;
}
public SketchStationName selectStationAt( float x, float y ) // (x,y) scene coords, view-mode
{
float min_dist = SketchDef.MIN_DISTANCE;
SketchStationName ret = null;
for ( SketchStationName st : mStations ) {
float d = st.sceneDistance( x, y );
if ( d < mCloseness && d < min_dist ) {
min_dist = d;
ret = st;
}
}
return ret;
}
public void deleteLine( SketchLinePath line )
{
mPaths.remove( line );
}
public void exportTherion( BufferedWriter out, String sketch_name, String proj_name )
{
// commandManager.exportTherion( out, sketch_name, plot_name );
try {
out.write("encoding utf-8");
out.newLine();
out.newLine();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.format("scrap %s -projection %s -scale [0 0 1 0 0.0 0.0 1 0.0 m]", sketch_name, proj_name );
out.write( sw.getBuffer().toString() );
out.newLine();
for ( NumStation st : stations ) {
StringWriter sw1 = new StringWriter();
PrintWriter pw1 = new PrintWriter( sw1 );
pw1.format( Locale.US, " point %.2f %.2f %.2f station -name %s\n\n", st.e, -st.s, -st.v, st.name );
out.write( sw1.getBuffer().toString() );
}
for ( SketchPath path : mPaths ) {
switch ( path.mType ) {
case DrawingPath.DRAWING_PATH_LINE:
case DrawingPath.DRAWING_PATH_AREA:
StringWriter sw2 = new StringWriter();
PrintWriter pw2 = new PrintWriter( sw2 );
SketchLinePath line = ( SketchLinePath ) path;
{
if ( path.mType == DrawingPath.DRAWING_PATH_LINE ) {
pw2.format(" line %s %s -shot %s %s\n", "3d",
BrushManager.mLineLib.getSymbolName( line.mThType ),
line.st1, line.st2 );
} else {
pw2.format(" area %s %s -shot %s %s\n", "3d",
BrushManager.mAreaLib.getSymbolName( line.mThType ),
line.st1, line.st2 );
}
}
for ( Vector pt : line.mLine.points ) {
pw2.format( Locale.US, " %.2f %.2f %.2f\n", pt.x, -pt.y, -pt.z );
}
{
if ( path.mType == DrawingPath.DRAWING_PATH_LINE ) {
pw2.format(" endline\n\n");
} else {
pw2.format(" endarea\n\n");
}
}
out.write( sw2.getBuffer().toString() );
break;
case DrawingPath.DRAWING_PATH_POINT:
SketchPointPath point = ( SketchPointPath ) path;
out.write( point.toTherion() );
break;
}
}
for ( SketchSurface surface : mSurfaces ) {
StringWriter sw3 = new StringWriter();
PrintWriter pw3 = new PrintWriter( sw3 );
surface.toTherion( pw3, "surface" );
out.write( sw3.getBuffer().toString() );
}
for ( SketchSurface surface : mJoins ) {
StringWriter sw4 = new StringWriter();
PrintWriter pw4 = new PrintWriter( sw4 );
surface.toTherion( pw4, "join" );
out.write( sw4.getBuffer().toString() );
}
// for ( SketchPointPath point : points ) {
// out.write( point.toTherion() );
// }
out.write("endscrap\n\n");
} catch ( IOException e ) {
Log.e( "DistoX", e.toString() );
}
}
private String readLine( BufferedReader br )
{
String line = null;
try {
line = br.readLine();
} catch ( IOException e ) {
// e.printStackTrace();
Log.e( "DistoX", e.toString() );
}
if ( line != null ) {
int comment = line.indexOf('#');
if ( comment == 0 ) {
return "";
} else if (comment > 0 ) {
line = line.substring( 0, comment );
}
line = line.trim();
line.replaceAll(" *", " ");
// line.replaceAll("\\s+", " ");
}
return line;
}
public boolean loadTh3( String filename, SymbolsPalette missingSymbols, SketchPainter painter )
{
float x, y, z, x1, y1, z1, x2, y2, z2;
int i1, i2, i3;
String type;
String label_text;
String fromStation = null, toStation = null;
if ( missingSymbols != null ) missingSymbols.resetSymbolLists();
// Log.v( "DistoX", "loadTh3 " + filename );
BrushManager.resetPointOrientations();
try {
FileReader fr = new FileReader( filename );
BufferedReader br = new BufferedReader( fr );
String line = null;
while ( (line = readLine(br)) != null ) {
int k1 = 1;
line = line.trim();
if ( line.length() == 0 ) continue;
String[] vals = line.split( " " );
if ( vals.length == 0 ) continue;
fromStation = null;
toStation = null;
for ( k1 = 1; k1<vals.length-2; ++k1 ) { // look for "-shot A B"
if ( vals[k1].equals( "-shot" ) ) {
fromStation = vals[k1+1];
toStation = vals[k1+2];
k1 += 3;
break;
}
}
int k = 0;
if ( vals[k].equals( "encoding" ) ) {
continue;
} else if ( vals[k].equals( "scrap" ) ) {
continue;
} else if ( vals[k].equals( "endscrap" ) ) {
continue;
} else if ( vals[k].equals( "surface" ) || vals[k].equals( "join" ) ) {
boolean is_surface = vals[k].equals( "surface" );
boolean is_join = vals[k].equals( "join" );
// ****** THERION SURFACE ********************************
// surface nr_vertices nr_triangles
// offset ...
// vertex
// index x y z
// ...
// endvertex
// side
// index v1 v2 <-- ignored
// ...
// endside
// triangle
// v1 v2 v3
// ...
// endtriangle
// endsurface
// -------------------------------------------------------
int nv = Integer.parseInt( vals[k1] ); // number of vertices
// int ns = Integer.parseInt( vals[k1+1] );
int nt = Integer.parseInt( vals[k1+1] );
// Log.v("DistoX", "surface nv " + nv + " nt " + nt );
line = readLine( br );
if ( ! line.equals( "endsurface" ) && ! line.equals( "endjoin" ) ) {
boolean ok = true;
SketchSurface surface = new SketchSurface( fromStation, toStation, painter );
if ( is_surface && fromStation.equals( mInfo.st1 ) && toStation.equals( mInfo.st2 ) ) {
mCurrentSurface = surface;
}
while ( ! line.equals( "endsurface" ) && ! line.equals( "endjoin" ) ) {
if ( line.startsWith( "vertex" ) ) { // read vertices
line = readLine( br );
while ( ! line.equals( "endvertex" ) ) {
String[] pt = line.split( "\\s+" );
int i = Integer.parseInt( pt[0] );
x = Float.parseFloat( pt[1] ); // / TDConst.TO_THERION;
y = - Float.parseFloat( pt[2] ); // / TDConst.TO_THERION;
z = - Float.parseFloat( pt[3] ); // / TDConst.TO_THERION;
i1 = surface.addVertex( i, x, y, z );
line = readLine( br );
}
if ( surface.mVertices.size() != nv ) {
Log.e("DistoX", "surface " + fromStation + " " + toStation + " vertex size mismatch " + nv + " " + surface.mVertices.size() );
nv = surface.mVertices.size();
ok = false;
}
} else if ( line.startsWith( "side" ) ) {
line = readLine( br );
while ( ! line.equals( "endside" ) ) {
// String[] pt = line.split( "\\s+" );
// i1 = Integer.parseInt( pt[0] ); // index
// i2 = Integer.parseInt( pt[1] ); // first vertex
// i3 = Integer.parseInt( pt[2] ); // second vertex
// surface.addSide( i1, i2, i3 );
line = readLine( br );
}
// if ( surface.sides.size() != ns ) {
// Log.e("DistoX", "surface " + fromStation + " " + toStation + " side size mismatch " + ns + " " + surface.sides.size() );
// ok = false;
// ns = surface.sides.size();
// }
} else if ( line.startsWith( "triangle" ) ) {
line = readLine( br );
while ( ! line.equals( "endtriangle" ) ) {
String[] pt = line.split( "\\s+" );
i1 = Integer.parseInt( pt[0] );
i2 = Integer.parseInt( pt[1] );
i3 = Integer.parseInt( pt[2] );
if ( i1 != i2 && i2 != i3 && i3 != i1 ) {
// int s23 = Integer.parseInt( pt[3] );
// int s31 = Integer.parseInt( pt[4] );
// int s12 = Integer.parseInt( pt[5] );
// surface.addTriangle( i1, i2, i3, s23, s31, s12 );
surface.addTriangle( i1, i2, i3 );
}
line = readLine( br );
}
if ( surface.mTriangles.size() != nt ) {
Log.e("DistoX", "surface " + fromStation + " " + toStation + " triangle size mismatch " + nt + " " + surface.mTriangles.size() );
ok = false;
nt = surface.mTriangles.size();
}
}
line = readLine( br );
}
// surface.dump();
if ( ok ) {
if ( is_surface ) {
surface.computeBorders();
mSurfaces.add( surface );
} else if ( is_join ) {
mJoins.add( surface );
}
}
}
} else if ( vals[k].equals( "point" ) ) {
// ****** THERION POINT **********************************
// int ptType = BrushManager.mPointLib.mSymbolNr;
// boolean has_orientation = false;
// float orientation = 0.0f;
// int scale = DrawingPointPath.SCALE_M;
// String options = null;
x = y = z = 0.0f;
if ( ++k < vals.length ) {
x = Float.parseFloat( vals[k] ); // / TDConst.TO_THERION; // th3 has east
}
if ( ++k < vals.length ) {
y = - Float.parseFloat( vals[k] ); // / TDConst.TO_THERION; // north
}
if ( ++k < vals.length ) {
z = - Float.parseFloat( vals[k] ); // / TDConst.TO_THERION; // pos-Z
}
if ( ++k < vals.length ) {
type = vals[k];
if ( type.equals( "station" ) ) {
// stations are automatic in the 3D model
continue;
} else {
int ptindex = BrushManager.mPointLib.getSymbolIndexByThName( type );
// for ( ; ptindex < BrushManager.mPointLib.mSymbolNr; ++ptindex ) {
// if ( type.equals( BrushManager.mPointLib.getSymbolThName( ptindex ) ) ) break;
// }
if ( ptindex >= 0 && ptindex < BrushManager.mPointLib.mSymbolNr ) {
SketchPointPath path = new SketchPointPath( ptindex, fromStation, toStation, x, y, z );
addPoint( path );
// parse options
while ( ++k < vals.length ) {
if ( vals[k].equals("-orientation") ) {
x = y = z = 0.0f;
if ( ++k < vals.length ) {
x = Float.parseFloat( vals[k] ); // / TDConst.TO_THERION;
}
if ( ++k < vals.length ) {
y = - Float.parseFloat( vals[k] ); // / TDConst.TO_THERION;
}
if ( ++k < vals.length ) {
z = - Float.parseFloat( vals[k] ); // / TDConst.TO_THERION;
}
path.setOrientation( new Vector(x,y,z), mInfo );
}
}
}
}
}
} else if ( vals[k].equals( "line" ) || vals[k].equals( "area" ) ) {
boolean is_line = vals[k].equals("line");
// ********* THERION LINES ************************************************************
int th_type = 0;
boolean closed = false;
String options = null;
if ( ++k < vals.length ) {
type = vals[k];
// assert type.equals("3d")
}
if ( ++k < vals.length ) {
if ( is_line ) {
th_type = BrushManager.mLineLib.getSymbolIndexByThName( vals[k] );
// int lnTypeMax = BrushManager.mLineLib.mSymbolNr;
// for ( th_type=0; th_type < lnTypeMax; ++th_type ) {
// if ( vals[k].equals( BrushManager.mLineLib.getSymbolThName( th_type ) ) ) break;
// }
} else {
closed = true;
th_type = BrushManager.mAreaLib.getSymbolIndexByThName( vals[k] );
// int lnTypeMax = BrushManager.mAreaLib.mSymbolNr;
// for ( th_type=0; th_type < lnTypeMax; ++th_type ) {
// if ( vals[k].equals( BrushManager.mAreaLib.getSymbolThName( th_type ) ) ) break;
// }
}
}
if ( th_type == -1 ) {
Log.v("DIstoX", "ERROR symbol not found " + vals[k] );
}
// TDLog.Log( TDLog.LOG_PLOT, "line type " + vals[1] );
for ( ++k; k < vals.length; ++k ) {
if ( vals[k].length() == 0 ) {
continue;
}
if ( vals[k].equals( "-close" ) ) {
if ( ++k < vals.length && vals[k].equals( "on" ) ) {
closed = true;
}
} else if ( vals[k].equals( "-shot" ) ) {
k += 2; // skip "-shot A B"
} else {
if ( options == null ) {
options = vals[k];
} else {
options += " " + vals[k];
}
}
}
// Log.v("DistoX", "load line " + vals[1] + " stations " + fromStation + " " + toStation );
// insert new line-path
// FIXME SOON line and area paint
line = readLine( br );
if ( ! ( line.equals( "endline" ) || line.equals( "endarea" ) ) ) {
SketchLinePath path = null;
if ( is_line ) {
path = new SketchLinePath( DrawingPath.DRAWING_PATH_LINE, th_type, fromStation, toStation, painter );
} else {
path = new SketchLinePath( DrawingPath.DRAWING_PATH_AREA, th_type, fromStation, toStation, painter );
}
// if ( closed ) path.mClosed = true;
// if ( options != null ) path.mOptions = options;
String[] pt = line.split( "\\s+" );
x = Float.parseFloat( pt[0] ); // / TDConst.TO_THERION;
y = - Float.parseFloat( pt[1] ); // / TDConst.TO_THERION;
z = - Float.parseFloat( pt[2] ); // / TDConst.TO_THERION;
path.addLinePoint( x, y, z );
while ( (line = readLine( br )) != null ) {
if ( line.equals( "endline" ) || line.equals( "endarea" ) ) {
if ( path != null ) {
addSketchPath( path );
}
break;
}
if ( path != null ) {
String[] vals2 = line.split( " " );
if ( vals2.length == 3 ) {
x = Float.parseFloat( vals2[0] ); // / TDConst.TO_THERION;
y = - Float.parseFloat( vals2[1] ); // / TDConst.TO_THERION;
z = - Float.parseFloat( vals2[2] ); // / TDConst.TO_THERION;
path.addLinePoint( x, y, z );
} else if ( vals2.length == 9 ) {
x1 = Float.parseFloat( vals2[0] ); // / TDConst.TO_THERION;
y1 = - Float.parseFloat( vals2[1] ); // / TDConst.TO_THERION;
z1 = - Float.parseFloat( vals2[2] ); // / TDConst.TO_THERION;
x2 = Float.parseFloat( vals2[3] ); // / TDConst.TO_THERION;
y2 = - Float.parseFloat( vals2[4] ); // / TDConst.TO_THERION;
z2 = - Float.parseFloat( vals2[5] ); // / TDConst.TO_THERION;
x = Float.parseFloat( vals2[6] ); // / TDConst.TO_THERION;
y = - Float.parseFloat( vals2[7] ); // / TDConst.TO_THERION;
z = - Float.parseFloat( vals2[8] ); // / TDConst.TO_THERION;
// path.addPoint3( x1, y1, z1, x2, y2, z2, x, y, z, false );
}
}
}
}
// }
} else {
Log.e("DistoX", "loadTh3: unknown line type >" + line + "<" );
}
}
} catch ( FileNotFoundException e ) {
// this is OK
} catch ( IOException e ) {
e.printStackTrace();
}
// remove repeated names
// Log.v( "DistoX", "loadTh3 " + filename + " done" );
return (missingSymbols != null )? missingSymbols.isOK() : true;
}
// -----------------------------------------------------------------
// SELECTION
SelectionPoint hotItem()
{
return mSelected.mHotItem;
}
// void shiftHotItem( float dx, float dy, float range )
void shiftHotItem( float dx, float dy )
{
// mSelected.shiftHotItem( dx, dy, range );
mSelected.shiftHotItem( dx, dy );
}
SelectionPoint nextHotItem()
{
return mSelected.nextHotItem();
}
SelectionPoint prevHotItem()
{
return mSelected.prevHotItem();
}
void clearSelected()
{
synchronized( mSelected ) {
mSelected.clear();
}
}
SketchVertex getVertexAt( float x, float y, float d ) // (x,y) canvas point
{
if ( mCurrentSurface == null ) return null;
return mCurrentSurface.getVertexAt( x, y, d );
}
SketchVertex getSelectedVertex()
{
if ( mCurrentSurface == null ) return null;
return mCurrentSurface.getSelectedVertex();
}
void setSelectedVertex( SketchVertex v )
{
if ( mCurrentSurface != null ) mCurrentSurface.setSelectedVertex( v );
}
void refineSurfaceAtSelectedVertex()
{
if ( mCurrentSurface == null ) return;
mCurrentSurface.refineAtSelectedVertex();
}
}