/* @file DrawingAreaPath.java * * @author marco corvi * @date nov 2011 * * @brief TopoDroid drawing: area-path (areas) * * The area border (line) path id DrawingPath.mPath * * -------------------------------------------------------- * 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.Matrix; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Shader; import android.graphics.Shader.TileMode; import java.io.PrintWriter; import java.io.StringWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; // import java.util.Iterator; // import java.util.List; import java.util.ArrayList; import java.util.Locale; import android.util.Log; /** */ public class DrawingAreaPath extends DrawingPointLinePath { // private static int area_id_cnt = 0; // private statis String makeId() // { // ++ area_id_cnt; // String ret = "a" + area_id_cnt; // return ret; // } int mAreaType; int mAreaCnt; double mOrientation; String mPrefix; // border/area name prefix (= scrap name) // boolean mVisible; // visible border in DrawingPointLinePath Shader mLocalShader = null; public DrawingAreaPath( int type, int cnt, String prefix, boolean visible ) { super( DrawingPath.DRAWING_PATH_AREA, visible, true ); mAreaType = type; mAreaCnt = cnt; mPrefix = (prefix != null && prefix.length() > 0)? prefix : "a"; if ( mAreaType < BrushManager.mAreaLib.mSymbolNr ) { setPaint( BrushManager.mAreaLib.getSymbolPaint( mAreaType ) ); } mOrientation = 0.0; if ( BrushManager.mAreaLib.isSymbolOrientable( mAreaType ) ) { // FIXME AREA_ORIENT mOrientation = BrushManager.getAreaOrientation( type ); mLocalShader = BrushManager.cloneAreaShader( mAreaType ); resetPaint(); mPaint.setShader( mLocalShader ); } } // @param id string "area id" (mPrefix + mAreaCnt ) public DrawingAreaPath( int type, String id, boolean visible ) { // visible = ?, closed = true super( DrawingPath.DRAWING_PATH_AREA, visible, true ); // TDLog.Log( TDLog.LOG_PLOT, "Drawing Area Path cstr type " + type + " id " + id ); mAreaType = type; mAreaCnt = 1; mPrefix = "a"; try { int pos = id.lastIndexOf("a") + 1; mPrefix = id.substring(0, pos); mAreaCnt = Integer.parseInt( id.substring(pos) ); } catch ( NumberFormatException e ) { TDLog.Error( "Drawing Area Path AreaCnt parse Int error: " + id.substring(1) ); } if ( mAreaType < BrushManager.mAreaLib.mSymbolNr ) { setPaint( BrushManager.mAreaLib.getSymbolPaint( mAreaType ) ); } } static DrawingAreaPath loadDataStream( int version, DataInputStream dis, float x, float y, SymbolsPalette missingSymbols ) { int type, cnt; boolean visible; float orientation; String fname, prefix; try { fname = dis.readUTF(); prefix = dis.readUTF(); cnt = dis.readInt(); visible = ( dis.read( ) == 1 ); orientation = dis.readFloat( ); int npt = dis.readInt( ); // BrushManager.mAreaLib.tryLoadMissingArea( fname ); type = BrushManager.mAreaLib.getSymbolIndexByFilename( fname ); // TDLog.Log( TDLog.LOG_PLOT, "A: " + fname + " " + cnt + " " + visible + " " + orientation + " NP " + npt ); if ( type < 0 ) { if ( missingSymbols != null ) missingSymbols.addAreaFilename( fname ); type = 0; } DrawingAreaPath ret = new DrawingAreaPath( type, cnt, prefix, visible ); ret.mOrientation = orientation; // setPaint( BrushManager.mAreaLib.getSymbolPaint( mAreaType ) ); int has_cp; float mX1, mY1, mX2, mY2, mX, mY; mX = x + dis.readFloat( ); mY = y + dis.readFloat( ); has_cp = dis.read(); if ( has_cp == 1 ) { // consume 4 floats mX1 = x + dis.readFloat(); mY1 = y + dis.readFloat(); mX2 = x + dis.readFloat(); mY2 = y + dis.readFloat(); } ret.addStartPoint( mX, mY ); // Log.v("DistoX", "A start " + mX + " " + mY ); for ( int k=1; k<npt; ++k ) { mX = x + dis.readFloat(); mY = y + dis.readFloat(); has_cp = dis.read(); // Log.v("DistoX", "A point " + mX + " " + mY + " " + has_cp ); if ( has_cp == 1 ) { mX1 = x + dis.readFloat(); mY1 = y + dis.readFloat(); mX2 = x + dis.readFloat(); mY2 = y + dis.readFloat(); ret.addPoint3( mX1, mY1, mX2, mY2, mX, mY ); } else { ret.addPoint( mX, mY ); } } ret.retracePath(); return ( npt < 3 )? null : ret; } catch ( IOException e ) { TDLog.Error( "AREA in error " + e.getMessage() ); // Log.v("DistoX", "AREA in error " + e.getMessage() ); } return null; } public void setAreaType( int t ) { mAreaType = t; if ( mAreaType < BrushManager.mAreaLib.mSymbolNr ) { setPaint( BrushManager.mAreaLib.getSymbolPaint( mAreaType ) ); } } @Override public void setPaint( Paint paint ) { mPaint = new Paint( paint ); } public int areaType() { return mAreaType; } @Override public void setOrientation( double angle ) { // Log.v( "DistoX", "Area path set orientation " + angle ); if ( ! BrushManager.mAreaLib.isSymbolOrientable( mAreaType ) ) return; mOrientation = angle; while ( mOrientation >= 360.0 ) mOrientation -= 360.0; while ( mOrientation < 0.0 ) mOrientation += 360.0; resetPaint(); } void shiftShaderBy( float dx, float dy, float s ) { if ( mLocalShader != null ) { // Log.v( "DistoX", "shift shader by " + dx + " " + dy + " scale " + s + " orient " + mOrientation ); Matrix mat = new Matrix(); // shader.getLocalMatrix( mat ); // set shader matrix even if shader did not have one mat.postRotate( (float)mOrientation ); mat.postTranslate( 4*dx, 4*dy ); mat.postScale( s/4, s/4 ); mLocalShader.setLocalMatrix( mat ); } } private void resetPaint() { // Log.v("DistoX", "arae path reset paint orientation " + mOrientation ); // Bitmap bitmap = BrushManager.getAreaBitmap( mAreaType ); // if ( bitmap != null ) if ( mLocalShader != null ) { Matrix mat = new Matrix(); mat.postRotate( (float)mOrientation ); // int w = bitmap.getWidth(); // int h = bitmap.getHeight(); // Bitmap bitmap1 = Bitmap.createBitmap( bitmap, 0, 0, w, h, mat, true ); // Bitmap bitmap2 = Bitmap.createBitmap( bitmap1, w/4, h/4, w/2, h/2 ); // BitmapShader shader = new BitmapShader( bitmap2, // BrushManager.getAreaXMode( mAreaType ), BrushManager.getAreaYMode( mAreaType ) ); // mPaint.setShader( shader ); mLocalShader.setLocalMatrix( mat ); } } @Override public String toTherion() { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); pw.format("line border -id %s%d -close on", mPrefix, mAreaCnt ); if ( ! isVisible() ) pw.format(" -visibility off"); // for ( LinePoint pt : mPoints ) pw.format("\n"); for ( LinePoint pt = mFirst; pt != null; pt = pt.mNext ) { pt.toTherion( pw ); } // if ( TDSetting.mXTherionAreas ) // NOTE xtherion needs an extra point { float dx = mLast.mX - mFirst.mX; float dy = mLast.mY - mFirst.mY; if ( dx*dx + dy*dy > 1.0e-7 ) { mFirst.toTherion( pw ); } } pw.format("endline\n"); pw.format("area %s", BrushManager.mAreaLib.getSymbolThName( mAreaType ) ); if ( BrushManager.mAreaLib.isSymbolOrientable( mAreaType ) ) { pw.format(Locale.US, " #orientation %.1f", mOrientation ); } pw.format("\n"); pw.format(" %s%d\n", mPrefix, mAreaCnt ); pw.format("endarea\n"); return sw.getBuffer().toString(); } @Override public void toCsurvey( PrintWriter pw, String cave, String branch ) { int layer = BrushManager.getAreaCsxLayer( mAreaType ); int type = 3; int cat = BrushManager.getAreaCsxCategory( mAreaType ); int pen = BrushManager.getAreaCsxPen( mAreaType ); int brush = BrushManager.getAreaCsxBrush( mAreaType ); // linetype: 0 spline, 1 bezier, 2 line pw.format(" <item layer=\"%d\" cave=\"%s\" branch=\"%s\" name=\"\" type=\"3\" category=\"%d\" linetype=\"2\" mergemode=\"0\">\n", layer, cave, branch, cat ); pw.format(" <pen type=\"%d\" />\n", pen); pw.format(" <brush type=\"%d\" />\n", brush); pw.format(" <points data=\""); boolean b = true; // for ( LinePoint pt : mPoints ) for ( LinePoint pt = mFirst; pt != null; pt = pt.mNext ) { float x = DrawingUtil.sceneToWorldX( pt.mX ); float y = DrawingUtil.sceneToWorldY( pt.mY ); pw.format(Locale.US, "%.2f %.2f ", x, y ); if ( b ) { pw.format("B "); b = false; } } pw.format("\" />\n"); pw.format(" </item>\n"); } @Override LinePoint next( LinePoint lp ) { if ( lp == null ) return null; if ( lp.mNext == null ) return mFirst; return lp.mNext; } @Override LinePoint prev( LinePoint lp ) { if ( lp == null ) return null; if ( lp.mPrev == null ) return mLast; return lp.mPrev; } @Override void toDataStream( DataOutputStream dos ) { String name = BrushManager.mAreaLib.getSymbolThName( mAreaType ); try { dos.write( 'A' ); dos.writeUTF( name ); dos.writeUTF( (mPrefix != null)? mPrefix : "" ); dos.writeInt( mAreaCnt ); dos.write( isVisible()? 1 : 0 ); dos.writeFloat( (float)mOrientation ); int npt = size(); // number of line points dos.writeInt( npt ); // Log.v("DistoX", "A to stream: " + name + " " + mAreaCnt + " " + isVisible() + " " + mOrientation + " np " + npt ); for ( LinePoint pt = mFirst; pt != null; pt = pt.mNext ) { pt.toDataStream( dos ); } // TDLog.Log( TDLog.LOG_PLOT, "A " + name + " " + npt ); } catch ( IOException e ) { TDLog.Error( "AREA out error " + e.toString() ); } // return 'A'; } }