/** @flile Sketch3dInfo.java * * @author marco corvi * @date jan 2013 * * @brief TopoDroid 3D sketch: path types (points, lines, and areas) * -------------------------------------------------------- * Copyright This sowftare is distributed under GPL-3.0 or later * See the file COPYING. * -------------------------------------------------------- */ package com.topodroid.DistoX; import java.util.Locale; import android.graphics.PointF; import android.graphics.Path; import android.util.Log; class Sketch3dInfo extends SketchShot { static final float mXScale = 1.0f; long surveyId; long id; String name; // sketch name String start; // start station (origin of ref. system, for NUM) // String st1; // current station // String st2; // forward station float xoffset_top, yoffset_top, zoom_top; // 2d scene offset, and zoom float xoffset_side, yoffset_side, zoom_side; // 2d scene offset, and zoom float xoffset_3d, yoffset_3d, zoom_3d; // 3d scene offset, and zoom float east, south, vert; // 3d origin float azimuth, clino; // 3d view angles [deg] float xcenter; float ycenter; // private float sin_alpha; // for the SIDE view // private float cos_alpha; // private float sin_gamma; // private float cos_gamma; // for the TOP view private float shotBearing; // shot azimuth private float shotClino; // shot clino NumStation station1; // station 1 NumStation station2; // station 2 // NumShot shot; // current shot float ne, ns, nv; // unit vector in the direction of sight float nxx, nxy, nxz; // unit vector of X-axis in the projection float nyx, nyy, nyz; // unit vector of Y-axis in the projection private float de1, ds1, dv1; // difference: Station2 - Station1 // private float dh1; // float dvdh; // ratio DV/DH // private float h0; private float x1, y1, z1; // station1 - origin (world coords) private float x2, y2, z2; // station2 - origin (world coords) private float ux, uy, uz; // shot unit vector private PointF p1, p2; // work points Sketch3dInfo() { super(null, null); p1 = new PointF(); p2 = new PointF(); start = "0"; } Vector shotUnit() { return new Vector( ux, uy, uz ); } Vector projectionOnShot( Vector v ) { float vu = ux * v.x + uy * v.y + uz * v.z; return new Vector( ux * vu, uy * vu, uz * vu ); } /** check if a triangle is forward */ boolean isForward( SketchTriangle t ) { return t.normal.x * ne + t.normal.y * ns + t.normal.z * nv > 0.0f; } void resetDirection() { azimuth = 0.0f; clino = 0.0f; setDirection(); } /** reset the direction of the viewpoint * @param a azimuth [degrees] * @param c clino [degrees] */ void resetDirection( float a, float c ) { azimuth = a; clino = c; setDirection(); } /** * @param da variation of azimuth * @param dc variation of clino */ void rotateBy3d( float da, float dc ) { worldToScene( x1, y1, z1, p1 ); azimuth -= da; if ( azimuth > 360 ) azimuth -= 360; if ( azimuth < 0 ) azimuth += 360; dc += clino; if ( dc > 180 ) dc -= 360; if ( dc < -180 ) dc += 360; clino = dc; setDirection(); worldToScene( x1, y1, z1, p2 ); xoffset_3d += (p1.x - p2.x); yoffset_3d += (p1.y - p2.y); } /** compute the triplet of unit vectors * ^ -vert | | ,(sa*cc, -ca*cc, -sc)_esv = -No Nx=(-ca,-sa,0) | ,' \|_________ east / \ south / \ Ny = No ^ Nx */ void setDirection() { float cc = TDMath.cosd( clino ); // cos and sin of clino and azimuth float sc = TDMath.sind( clino ); float ca = TDMath.cosd( (azimuth+180) ); float sa = TDMath.sind( (azimuth+180) ); ne = - sa * cc; ns = ca * cc; nv = sc; nxx = - ca; nxy = - sa; nxz = 0; nyx = sa * sc; nyy = - ca * sc; nyz = cc; } String getDirectionString() { return String.format(Locale.US, "%.0f %.0f", azimuth, clino ); // can skip Locale } String getShotString() { return String.format(Locale.US, "%s-%s %.0f %.0f", st1, st2, shotBearing, shotClino ); // can skip Locale } void setStations( NumStation s1, NumStation s2, DistoXDBlock blk, boolean set_origin ) { if ( set_origin ) { east = s1.e; south = s1.s; vert = s1.v; xoffset_top = xcenter; yoffset_top = ycenter; xoffset_side = xcenter; yoffset_side = ycenter; xoffset_3d = xcenter; yoffset_3d = ycenter; } else { /* anything to do ? */ } if ( blk != null ) { shotBearing = blk.mBearing; shotClino = blk.mClino; } else { shotBearing = 0f; shotClino = 0f; } st1 = s1.name; st2 = s2.name; station1 = s1; station2 = s2; de1 = station2.e - station1.e; ds1 = station2.s - station1.s; dv1 = station2.v - station1.v; float dh1 = TDMath.sqrt( de1*de1 + ds1*ds1 ); if ( dh1 < 0.01f ) dh1 += 0.01f; // regularize by adding 1 cm // sin_alpha = de1/dh1; // cos_alpha = ds1/dh1; // dvdh = dv1 / dh1; // len is guaranteed non-zero (since dh1 >= 0.01) float len = TDMath.sqrt( dh1*dh1 + dv1*dv1 ); // sin_gamma = dv1 / len; // == uz // cos_gamma = dh1 / len; azimuth = 0.0f; clino = 0.0f; x1 = (station1.e - east); y1 = (station1.s - south); z1 = (station1.v - vert); x2 = (station2.e - east); y2 = (station2.s - south); z2 = (station2.v - vert); ux = de1 / len; uy = ds1 / len; uz = dv1 / len; // float det = 1.0f/(ds1*ds1 + de1*de1); // float a1 = station1.e * ds1 - station1.s * de1; // h0 = (station1.e-east)*sin_alpha + (station1.s-south)*cos_alpha; } float distance3d( Vector v ) { float c = v.x * ux + v.y * uy + v.z * uz; float x = v.x - ux * c; float y = v.y - uy * c; float z = v.z - uz * c; return TDMath.sqrt( x*x + y*y + z*z ); } /** * @param x X scene coord * @param y Y scene coord * * (x1,y1,z1) = station1 - origin * (x2,y2,z2) = station2 - origin * * (xx1,yy1) station1 scene coords */ float sceneProjOnShot( float x, float y, Vector v ) { float ret = -2.0f; // line abscissa: 0 at station1, 1 at station2 float xx1 = nxx * x1 + nxy * y1 + nxz * z1; float yy1 = nyx * x1 + nyy * y1 + nyz * z1; float xx2 = nxx * x2 + nxy * y2 + nxz * z2; float yy2 = nyx * x2 + nyy * y2 + nyz * z2; float a = yy2 - yy1; float b = xx1 - xx2; float c = xx2 * yy1 - xx1 * yy2; float det = a*a + b*b; // distance form the line: float d = Math.abs( a * x + b * y + c )/TDMath.sqrt(det); xx2 -= xx1; yy2 -= yy1; if ( d > 0.1f * (Math.abs(xx2) + Math.abs(yy2)) ) return -2.0f; float xx0 = ( b*b*x - a*b*y - a*c)/det; float yy0 = (-a*b*x + a*a*y - b*c)/det; if ( Math.abs(xx2) > Math.abs(yy2) ) { // ratio on X // float xx0 = ( b*b*x - a*b*y - a*c)/det; ret = ( xx0 - xx1 ) / xx2; } else { // float yy0 = (-a*b*x + a*a*y - b*c)/det; ret = ( yy0 - yy1 ) / yy2; } v.x = station1.e + ret * de1; v.y = station1.s + ret * ds1; v.z = station1.v + ret * dv1; return ret; } /** * subtract the origin from the vector * and compute the projection on the scene */ float worldToSceneOrigin( Vector v, PointF p ) { if ( v == null ) return 0f; return worldToSceneOrigin( v.x, v.y, v.z, p ); } float worldToSceneOrigin( float x, float y, float z, PointF p ) { x -= east; y -= south; z -= vert; p.x = nxx * x + nxy * y + nxz * z; p.y = nyx * x + nyy * y + nyz * z; return ne * x + ns * y + nv * z; } private void worldToScene( float x, float y, float z, PointF p ) { p.x = nxx * x + nxy * y + nxz * z; p.y = nyx * x + nyy * y + nyz * z; } float canvasToSceneX( float x ) { return (x)/zoom_3d - xoffset_3d; } float canvasToSceneY( float y ) { return (y)/zoom_3d - yoffset_3d; } float sceneToCanvasX( float x ) { return (x+xoffset_3d) * zoom_3d; } float sceneToCanvasYtop( float y ) { return (y+yoffset_3d) * zoom_3d; } Vector sceneToWorld( float x, float y ) { return new Vector( nxx * x + nyx * y, nxy * x + nyy * y, nxz * x + nyz * y ); } Vector sceneToWorld( LinePoint p ) { return sceneToWorld( p.mX, p.mY ); } Vector sceneToWorld( PointF p ) { return sceneToWorld( p.x, p.y ); } void shiftOffset3d( float x, float y ) { xoffset_3d += x / zoom_3d; yoffset_3d += y / zoom_3d; } void changeZoom3d( float f ) { float z = zoom_3d; zoom_3d *= f; z = 1/z - 1/zoom_3d; xoffset_3d -= xcenter * z; yoffset_3d -= ycenter * z; } void resetZoom3d( float x, float y, float z ) { xoffset_3d = x/2; yoffset_3d = y/2; zoom_3d = z; } /** the line point(s) are already in the scene reference frame */ Vector projTo3d( LinePoint p ) { return sceneToWorld( p ); } }