/* @file ProjectionCommandManager.java * * @author marco corvi * @date mar 2016 * * @brief TopoDroid projected profile azimuth: commands manager * -------------------------------------------------------- * 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.Matrix; import android.graphics.Bitmap; import android.graphics.PorterDuff; // import android.graphics.PointF; // import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; // import android.graphics.Path.Direction; import android.os.Handler; import java.util.Iterator; import java.util.List; // import java.util.Locale; import java.util.Collections; import java.util.ArrayList; import java.util.Locale; import android.util.Log; /** */ public class ProjectionCommandManager { private static final int BORDER = 20; RectF mBBox = null; private List<DrawingPath> mGridStack1; private List<DrawingPath> mGridStack10; private List<DrawingPath> mGridStack100; private List<DrawingPath> mLegsStack; private List<DrawingPath> mSplaysStack; private List<ICanvasCommand> mCurrentStack; private List<DrawingStationPath> mUserStations; // user-inserted stations private List<ICanvasCommand> mRedoStack; // private List<DrawingPath> mHighlight; // highlighted path private List<DrawingStationName> mStations; // survey stations private int mMaxAreaIndex; // max index of areas in this plot private Selection mSelection; private SelectionSet mSelected; private boolean mDisplayPoints; private Matrix mMatrix; private float mScale; // current zoom: value of 1 pl in scene space List<DrawingPath> getLegs() { return mLegsStack; } List<DrawingPath> getSplays() { return mSplaysStack; } List<ICanvasCommand> getCommands() { return mCurrentStack; } List<DrawingStationName> getStations() { return mStations; } List<DrawingStationPath> getUserStations() { return mUserStations; } // void checkLines() // { // synchronized( mCurrentStack ) { // int size = mCurrentStack.size(); // for ( int i1 = 0; i1 < size; ++i1 ) { // ICanvasCommand cmd1 = mCurrentStack.get( i1 ); // DrawingPath path1 = (DrawingPath)cmd1; // if ( path1.mType != DrawingPath.DRAWING_PATH_LINE ) continue; // DrawingLinePath line1 = (DrawingLinePath)path1; // for ( int i2 = i1+1; i2 < size; ++i2 ) { // ICanvasCommand cmd2 = mCurrentStack.get( i2 ); // DrawingPath path2 = (DrawingPath)cmd2; // if ( path2.mType != DrawingPath.DRAWING_PATH_LINE ) continue; // DrawingLinePath line2 = (DrawingLinePath)path2; // if ( line1.overlap( line2 ) > 1 ) { // Log.v("DistoX", "LINE OVERLAP " + i1 + "-" + i2 + " total nr. " + size ); // // for ( int i=0; i<size; ++i ) { // // ICanvasCommand cmd = mCurrentStack.get( i ); // // DrawingPath path = (DrawingPath)cmd; // // if ( path.mType != DrawingPath.DRAWING_PATH_LINE ) continue; // // DrawingLinePath line = (DrawingLinePath)path; // // line.dump(); // // } // Log.v("DistoX", "LINE1 "); // line1.dump(); // Log.v("DistoX", "LINE2 "); // line2.dump(); // throw new RuntimeException(); // } // } // } // } // } private void flipXAxes( List<DrawingPath> paths ) { final float z = 1/mScale; final Iterator i1 = paths.iterator(); while ( i1.hasNext() ){ final DrawingPath drawingPath = (DrawingPath) i1.next(); drawingPath.flipXAxis( z ); } } void flipXAxis(float z) { synchronized( mGridStack1 ) { flipXAxes( mGridStack1 ); flipXAxes( mGridStack10 ); flipXAxes( mGridStack100 ); } synchronized( mLegsStack ) { flipXAxes( mLegsStack ); } synchronized( mSplaysStack ) { flipXAxes( mSplaysStack ); } synchronized( mStations ) { for ( DrawingStationName st : mStations ) { st.flipXAxis(z); } } if ( mCurrentStack != null ) { Selection selection = new Selection(); synchronized( mCurrentStack ) { final Iterator i = mCurrentStack.iterator(); while ( i.hasNext() ){ final ICanvasCommand cmd = (ICanvasCommand) i.next(); if ( cmd.commandType() == 0 ) { cmd.flipXAxis(z); DrawingPath path = (DrawingPath)cmd; if ( path.mType == DrawingPath.DRAWING_PATH_LINE ) { DrawingLinePath line = (DrawingLinePath)path; line.flipReversed(); } selection.insertPath( path ); } } } mSelection = selection; } } void shiftDrawing( float x, float y ) { // if ( mStations != null ) { // synchronized( mStations ) { // for ( DrawingStationName st : mStations ) { // st.shiftBy( x, y ); // } // } // } if ( mCurrentStack != null ){ synchronized( mCurrentStack ) { final Iterator i = mCurrentStack.iterator(); while ( i.hasNext() ){ final ICanvasCommand cmd = (ICanvasCommand) i.next(); cmd.shiftPathBy( x, y ); } } } if ( mSelection != null ) { synchronized( mSelection ) { mSelection.shiftSelectionBy( x, y ); } } } public ProjectionCommandManager() { // mBBox = new RectF(); mGridStack1 = Collections.synchronizedList(new ArrayList<DrawingPath>()); mGridStack10 = Collections.synchronizedList(new ArrayList<DrawingPath>()); mGridStack100 = Collections.synchronizedList(new ArrayList<DrawingPath>()); mLegsStack = Collections.synchronizedList(new ArrayList<DrawingPath>()); mSplaysStack = Collections.synchronizedList(new ArrayList<DrawingPath>()); mCurrentStack = Collections.synchronizedList(new ArrayList<ICanvasCommand>()); mUserStations = Collections.synchronizedList( new ArrayList<DrawingStationPath>()); mRedoStack = Collections.synchronizedList(new ArrayList<ICanvasCommand>()); // mHighlight = Collections.synchronizedList(new ArrayList<DrawingPath>()); mStations = Collections.synchronizedList(new ArrayList<DrawingStationName>()); mMatrix = new Matrix(); // identity mSelection = new Selection(); mSelected = new SelectionSet(); mMaxAreaIndex = 0; } int getNextAreaIndex() { ++mMaxAreaIndex; return mMaxAreaIndex; } List< DrawingPath > getIntersectionShot( LinePoint p1, LinePoint p2 ) { List< DrawingPath > ret = new ArrayList< DrawingPath >(); for ( DrawingPath p : mLegsStack ) { if ( p.mType == DrawingPath.DRAWING_PATH_FIXED ) { if ( p.intersect( p1.mX, p1.mY, p2.mX, p2.mY, null ) ) { ret.add( p ); } } } return ret; } DrawingStationName getStationAt( float x, float y ) // x,y canvas coords { // Log.v("DistoX", "get station at " + x + " " + y ); for ( DrawingStationName st : mStations ) { // Log.v("DistoX", "station at " + st.cx + " " + st.cy ); if ( Math.abs( x - st.cx ) < TDSetting.mCloseness && Math.abs( y - st.cy ) < TDSetting.mCloseness ) return st; } return null; } void setDisplayPoints( boolean display ) { mDisplayPoints = display; } boolean isSelectable() { return mSelection != null; } void clearReferences() { synchronized( mGridStack1 ) { mGridStack1.clear(); mGridStack10.clear(); mGridStack100.clear(); } synchronized( mLegsStack ) { mLegsStack.clear(); } synchronized( mSplaysStack ) { mSplaysStack.clear(); } synchronized( mStations ) { mStations.clear(); } } void clearDrawing() { mGridStack1.clear(); mGridStack10.clear(); mGridStack100.clear(); mLegsStack.clear(); mSplaysStack.clear(); mStations.clear(); } public void setTransform( float dx, float dy, float s ) { mMatrix = new Matrix(); mMatrix.postTranslate( dx, dy ); mMatrix.postScale( s, s ); mScale = 1 / s; // mBBox.left = - dx; // scene coords // mBBox.right = mScale * TopoDroidApp.mDisplayWidth - dx; // mBBox.top = - dy; // mBBox.bottom = mScale * TopoDroidApp.mDisplayHeight - dy; } // oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo // FIXME LEGS_SPLAYS // void resetFixedPaint( Paint paint ) // { // if( mLegsStack != null ) { // synchronized( mLegsStack ) { // final Iterator i = mLegsStack.iterator(); // while ( i.hasNext() ){ // final DrawingPath path = (DrawingPath) i.next(); // if ( path.mBlock == null || ( ! path.mBlock.mMultiBad ) ) { // path.setPaint( paint ); // } // } // } // } // if( mSplaysStack != null ) { // synchronized( mSplaysStack ) { // final Iterator i = mSplaysStack.iterator(); // while ( i.hasNext() ){ // final DrawingPath path = (DrawingPath) i.next(); // if ( path.mBlock == null || ( ! path.mBlock.mMultiBad ) ) { // path.setPaint( paint ); // } // } // } // } // } public void addLegPath( DrawingPath path ) { if ( mLegsStack == null ) return; synchronized( mLegsStack ) { mLegsStack.add( path ); } } public void addSplayPath( DrawingPath path ) { if ( mSplaysStack == null ) return; synchronized( mSplaysStack ) { mSplaysStack.add( path ); } } public void addGrid( DrawingPath path, int k ) { if ( mGridStack1 == null ) return; synchronized( mGridStack1 ) { switch (k) { case 1: mGridStack1.add( path ); break; case 10: mGridStack10.add( path ); break; case 100: mGridStack100.add( path ); break; } } } public void executeAll( Canvas canvas ) { if ( canvas == null ) { TDLog.Error( "drawing executeAll null canvas"); return; } if ( mGridStack1 != null ) { synchronized( mGridStack1 ) { if ( mScale < 1 ) { final Iterator i1 = mGridStack1.iterator(); while ( i1.hasNext() ){ final DrawingPath drawingPath = (DrawingPath) i1.next(); drawingPath.draw( canvas, mMatrix, mScale, mBBox ); } } if ( mScale < 10 ) { final Iterator i10 = mGridStack10.iterator(); while ( i10.hasNext() ){ final DrawingPath drawingPath = (DrawingPath) i10.next(); drawingPath.draw( canvas, mMatrix, mScale, mBBox ); } } final Iterator i100 = mGridStack100.iterator(); while ( i100.hasNext() ){ final DrawingPath drawingPath = (DrawingPath) i100.next(); drawingPath.draw( canvas, mMatrix, mScale, mBBox ); } } } if ( mLegsStack != null ) { synchronized( mLegsStack ) { for ( DrawingPath path : mLegsStack ) { path.draw( canvas, mMatrix, mScale, mBBox ); } } } if ( mSplaysStack != null ) { synchronized( mSplaysStack ) { for ( DrawingPath path : mSplaysStack ) { path.draw( canvas, mMatrix, mScale, mBBox ); } } } if ( mStations != null ) { synchronized( mStations ) { for ( DrawingStationName st : mStations ) { st.draw( canvas, mMatrix, mScale, mBBox ); } } } } // RectF computeBBox() // { // float xmin=1000000f, xmax=-1000000f, // ymin=1000000f, ymax=-1000000f; // synchronized( mCurrentStack ) { // final Iterator i = mCurrentStack.iterator(); // while ( i.hasNext() ) { // final ICanvasCommand cmd = (ICanvasCommand) i.next(); // if ( cmd.commandType() != 0 ) continue; // DrawingPath p = (DrawingPath) cmd; // // RectF bbox = p.mBBox; // if ( p.left < xmin ) xmin = p.left; // if ( p.right > xmax ) xmax = p.right; // if ( p.top < ymin ) ymin = p.top; // if ( p.bottom > ymax ) ymax = p.bottom; // } // } // return new RectF( xmin, ymin, xmax, ymax ); // left top right bottom // } // called by DrawingSurface::addDrawingStationName public void addStation( DrawingStationName st ) { synchronized( mStations ) { mStations.add( st ); } } }