/* * Copyright (c) 2002-2006 Samit Basu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "HandleSurface.hpp" #include "HandleAxis.hpp" #include HandleSurface::HandleSurface() { ConstructProperties(); SetupDefaults(); } HandleSurface::~HandleSurface() { } std::vector HandleSurface::GetLimits() { std::vector limits; UpdateState(); Array xdata(ArrayPropertyLookup("xdata")); Array ydata(ArrayPropertyLookup("ydata")); Array zdata(ArrayPropertyLookup("zdata")); Array cdata(ArrayPropertyLookup("cdata")); limits.push_back(ArrayMin(xdata)); limits.push_back(ArrayMax(xdata)); limits.push_back(ArrayMin(ydata)); limits.push_back(ArrayMax(ydata)); limits.push_back(ArrayMin(zdata)); limits.push_back(ArrayMax(zdata)); limits.push_back(ArrayMin(cdata)); limits.push_back(ArrayMax(cdata)); std::vector alphadata(VectorPropertyLookup("alphadata")); limits.push_back(VecMin(alphadata)); limits.push_back(VecMax(alphadata)); return limits; } void HandleSurface::ConstructProperties() { //! //@Module SURFACEPROPERTIES Surface Object Properties //@@Section HANDLE //@@Usage //Below is a summary of the properties for the axis. //\begin{itemize} // \item @|alphadata| - @|vector| - This is a vector that // should contain as many elements as the surface data itself @|cdata|, // or a single scalar. For a single scalar, all values of the surface // take on the same transparency. Otherwise, the transparency of // each pixel is determined by the corresponding value from the @|alphadata| // vector. // \item @|alphadatamapping| - @|{'scaled','direct','none'}| - For @|none| // mode (the default), no transparency is applied to the data. For @|direct| // mode, the vector @|alphadata| contains values between @[0,M-1]| where // @|M| is the length of the alpha map stored in the figure. For @|scaled| // mode, the @|alim| vector for the figure is used to linearly rescale the // alpha data prior to lookup in the alpha map. // \item @|ambientstrength| - Not used. // \item @|backfacelighting| - Not used. // \item @|cdata| - @|array| - This is either a @|M x N| array or an // @|M x N x 3| array. If the data is @|M x N| the surface is a scalar // surface (indexed mode), where the color associated with each surface pixel // is computed using the colormap and the @|cdatamapping| mode. If the // data is @|M x N x 3| the surface is assumed to be in RGB mode, and the // colorpanes are taken directly from @|cdata| (the colormap is ignored). // Note that in this case, the data values must be between @[0,1]| for each // color channel and each point on the surface. // \item @|cdatamapping| - @|{'scaled','direct'}| - For @|scaled| (the // default), the pixel values are scaled using the @|clim| vector for the // figure prior to looking up in the colormap. For @|direct| mode, the // pixel values must be in the range @|[0,N-1| where @|N| is the number of // colors in the colormap. // \item @|children| - Not used. // \item @|diffusestrength| - Not used. // \item @|edgealpha| - @|{'flat','interp','scalar'}| - Controls how the // transparency is mapped for the edges of the surface. // \item @|edgecolor| - @|{'flat','interp','none',colorspec}| - Specifies // how the edges are colored. For @|'flat'| the edges are flat colored, // meaning that the line segments that make up the edges are not shaded. // The color for the line is determined by the first edge point it is connected // to. // \item @|edgelighting| - Not used. // \item @|facealpha| - @|{'flat','interp','texturemap',scalar}| - Controls // how the transparency of the faces of the surface are controlled. For // flat shading, the faces are constant transparency. For interp mode, the faces // are smoothly transparently mapped. If set to a scalar, all faces have the // same transparency. // \item @|facecolor| - @|{'none','flat','interp',colorspec}| - Controls // how the faces are colored. For @|'none'| the faces are uncolored, and // the surface appears as a mesh without hidden lines removed. For @|'flat'| // the surface faces have a constant color. For @|'interp'| smooth shading // is applied to the surface. And if a colorspec is provided, then the // faces all have the same color. // \item @|facelighting| - Not used. // \item @|linestyle| - @|{'-','--',':','-.','none'}| - The style of the line used // to draw the edges. // \item @|linewidth| - @|scalar| - The width of the line used to draw the edges. // \item @|marker| - @|{'+','o','*','.','x','square','s','diamond','d','^','v','>','<'}| - // The marker for data points on the line. Some of these are redundant, as @|'square'| // @|'s'| are synonyms, and @|'diamond'| and @|'d'| are also synonyms. // \item @|markeredgecolor| - @|colorspec| - The color used to draw the marker. For some // of the markers (circle, square, etc.) there are two colors used to draw the marker. // This property controls the edge color (which for unfilled markers) is the primary // color of the marker. // \item @|markerfacecolor| - @|colorspec| - The color used to fill the marker. For some // of the markers (circle, square, etc.) there are two colors used to fill the marker. // \item @|markersize| - @|scalar| - Control the size of the marker. Defaults to 6, which // is effectively the radius (in pixels) of the markers. // \item @|meshstyle| - @|{'both','rows','cols}| - This property controls how the mesh is // drawn for the surface. For @|rows| and @|cols| modes, only one set of edges is drawn. // \item @|normalmode| - Not used. // \item @|parent| - @|handle| - The axis containing the surface. // \item @|specularcolorreflectance| - Not used. // \item @|specularexponent| - Not used. // \item @|specularstrength| - Not used. // \item @|tag| - @|string| - You can set this to any string you want. // \item @|type| - @|string| - Set to the string @|'surface'|. // \item @|userdata| - @|array| - Available to store any variable you // want in the handle object. // \item @|vertexnormals| - Not used. // \item @|xdata| - @|array| - Must be a numeric array of size @|M x N| which contains // the x location of each point in the defined surface. Must be the same size as @|ydata| // and @|zdata|. Alternately, you can specify an array of size @|1 x N| in which case // FreeMat replicates the vector to fill out an @|M x N| matrix. // \item @|xdatamode| - @|{'auto','manual'}| - When set to @|auto| then FreeMat will // automatically generate the x coordinates. // \item @|ydata| - @|array| - Must be a numeric array of size @|M x N| which contains // the y location of each point in the defined surface. Must be the same size as @|xdata| // and @|zdata|. Alternately, you can specify an array of size @|M x 1| in which case // FreeMat replicates the vector to fill out an @|M x N| matrix. // \item @|ydatamode| - @|{'auto','manual'}| - When set to @|auto| then FreeMat will // automatically generate the y coordinates. // \item @|zdata| - @|array| - Must be a numeric array of size @|M x N| which contains // the y location of each point in the defined surface. Must be the same size as @|xdata| // and @|ydata|. // \item @|visible| - @|{'on','off'}| - Controls whether the surface is // visible or not. //\end{itemize} //! AddProperty(new HPVector, "alphadata"); AddProperty(new HPMappingMode, "alphadatamapping"); AddProperty(new HPScalar,"ambientstrength"); AddProperty(new HPBackFaceLighting,"backfacelighting"); AddProperty(new HPArray, "cdata"); AddProperty(new HPDataMappingMode, "cdatamapping"); AddProperty(new HPAutoManual, "cdatamode"); AddProperty(new HPHandles,"children"); AddProperty(new HPScalar,"diffusestrength"); AddProperty(new HPEdgeAlpha,"edgealpha"); AddProperty(new HPColorInterp,"edgecolor"); AddProperty(new HPLightingMode,"edgelighting"); AddProperty(new HPFaceAlpha,"facealpha"); AddProperty(new HPColorInterp,"facecolor"); AddProperty(new HPLightingMode,"facelighting"); AddProperty(new HPLineStyle,"linestyle"); AddProperty(new HPScalar,"linewidth"); AddProperty(new HPSymbol,"marker"); AddProperty(new HPAutoFlatColor,"markeredgecolor"); AddProperty(new HPAutoFlatColor,"markerfacecolor"); AddProperty(new HPScalar,"markersize"); AddProperty(new HPRowColumns,"meshstyle"); AddProperty(new HPAutoManual,"normalmode"); AddProperty(new HPHandles,"parent"); AddProperty(new HPScalar,"specularcolorreflectance"); AddProperty(new HPScalar,"specularexponent"); AddProperty(new HPScalar,"specularstrength"); AddProperty(new HPString,"tag"); AddProperty(new HPString,"type"); AddProperty(new HPArray,"userdata"); AddProperty(new HPArray,"vertexnormals"); AddProperty(new HPArray,"xdata"); AddProperty(new HPAutoManual,"xdatamode"); AddProperty(new HPArray,"ydata"); AddProperty(new HPAutoManual,"ydatamode"); AddProperty(new HPArray,"zdata"); AddProperty(new HPOnOff,"visible"); } void HandleSurface::SetupDefaults() { HPVector *hp = (HPVector*) LookupProperty("alphadata"); std::vector gp; gp.push_back(1.0); hp->Data(gp); SetConstrainedStringDefault("alphadatamapping","none"); SetScalarDefault("ambientstrength",0.55); SetConstrainedStringDefault("backfacelighting","unlit"); SetConstrainedStringDefault("cdatamapping","scaled"); SetConstrainedStringDefault("cdatamode","auto"); SetScalarDefault("diffusestrength",0.6); SetScalarDefault("specularcolorreflectance",0.4); SetScalarDefault("specularexponent",0.1); SetScalarDefault("specularstrength",0.5); SetStringDefault("type","image"); SetConstrainedStringDefault("visible","on"); SetConstrainedStringScalarDefault("edgealpha","scalar",1); SetConstrainedStringColorDefault("edgecolor","colorspec",0,0,0); SetConstrainedStringDefault("edgelighting","none"); SetConstrainedStringScalarDefault("facealpha","scalar",1); SetConstrainedStringDefault("facecolor","flat"); SetConstrainedStringDefault("facelighting","none"); SetConstrainedStringDefault("linestyle","-"); SetScalarDefault("linewidth",0.5); SetConstrainedStringDefault("marker","none"); SetConstrainedStringColorDefault("markeredgecolor","auto",0,0,0); SetConstrainedStringColorDefault("markerfacecolor","none",0,0,0); SetScalarDefault("markersize",6); SetConstrainedStringDefault("meshstyle","both"); SetConstrainedStringDefault("normalmode","auto"); SetStringDefault("type","surface"); SetStringDefault("xdatamode","auto"); SetStringDefault("ydatamode","auto"); } void HandleSurface::DoAutoXMode() { Array zdata(ArrayPropertyLookup("zdata")); Array xdata(Array::doubleMatrixConstructor(zdata.rows(),zdata.columns())); double *dp = (double*) xdata.getReadWriteDataPointer(); int cols(zdata.columns()); int rows(zdata.rows()); for (int j=0;jData(xdata); } void HandleSurface::DoAutoYMode() { Array zdata(ArrayPropertyLookup("zdata")); Array ydata(Array::doubleMatrixConstructor(zdata.rows(),zdata.columns())); double *dp = (double*) ydata.getReadWriteDataPointer(); int cols(zdata.columns()); int rows(zdata.rows()); for (int j=0;jData(ydata); } void HandleSurface::DoAutoCMode() { Array zdata(ArrayPropertyLookup("zdata")); HPArray *hp = (HPArray*) LookupProperty("cdata"); hp->Data(zdata); } void HandleSurface::UpdateState() { if (HasChanged("xdata")) ToManual("xdatamode"); if (HasChanged("ydata")) ToManual("ydatamode"); if (HasChanged("cdata")) ToManual("cdatamode"); if (IsAuto("xdatamode")) DoAutoXMode(); if (IsAuto("ydatamode")) DoAutoYMode(); if (IsAuto("cdatamode")) DoAutoCMode(); HandleImage::UpdateCAlphaData(); } /* 0 q1 1 q2 2 */ Array HandleSurface::GetCoordinateMatrix(std::string name, bool isXcoord) { // Get the elevation data from the object Array zdata(ArrayPropertyLookup("zdata")); int zrows(zdata.rows()); int zcols(zdata.columns()); if (StringCheck(name+"mode","manual")) { // not auto mode... Array cdata(ArrayPropertyLookup(name)); if (cdata.isVector() && ((isXcoord && (cdata.getLength() == zcols)) || (!isXcoord && (cdata.getLength() == zrows)))) { cdata.promoteType(FM_DOUBLE); const double *qp = (const double*) cdata.getDataPointer(); Array mat(Array::doubleMatrixConstructor(zrows,zcols)); double *dp = (double*) mat.getReadWriteDataPointer(); for (int i=0;i > HandleSurface::BuildQuadsNoTexMap(HPConstrainedStringColor* cp, HPConstrainedStringScalar* ap) { // Get the x,y,z & color data points std::vector > retval; Array xdata(GetCoordinateMatrix("xdata",true)); xdata.promoteType(FM_DOUBLE); Array ydata(GetCoordinateMatrix("ydata",false)); ydata.promoteType(FM_DOUBLE); Array zdata(ArrayPropertyLookup("zdata")); zdata.promoteType(FM_DOUBLE); if ((xdata.getLength() != zdata.getLength()) || (xdata.getLength() != ydata.getLength())) return retval; if (zdata.isEmpty()) return retval; double *xdp = (double*) xdata.getDataPointer(); double *ydp = (double*) ydata.getDataPointer(); double *zdp = (double*) zdata.getDataPointer(); int rows = zdata.rows(); int cols = zdata.columns(); if (cp->Is("interp") && ((img.height() < rows) || (img.width() < cols))) return retval; if (ap->Is("interp") && ((img.height() < rows) || (img.width() < cols))) return retval; if (cp->Is("flat") && ((img.height() < rows-1) || (img.width() < cols-1))) return retval; if (ap->Is("flat") && ((img.height() < rows-1) || (img.width() < cols-1))) return retval; if (cp->Is("none")) return retval; QRgb *dummyline; if (cp->Is("colorspec") || ap->Is("scalar")) { dummyline = new QRgb[cols]; double r = 0; double g = 0; double b = 0; double alphaval = 1.0; if (ap->Is("scalar")) alphaval = ap->Scalar(); if (cp->Is("colorspec")) { std::vector p(cp->ColorSpec()); if (p[0] == -1) return retval; r = p[0]; g = p[1]; b = p[2]; } for (int i=0;iIs("interp")) { cbits1 = (QRgb*) img.scanLine(i); cbits2 = (QRgb*) img.scanLine(i+1); col_lim = cols-1; } else if (cp->Is("flat")) { cbits1 = (QRgb*) img.scanLine(i); cbits2 = (QRgb*) img.scanLine(i); col_lim = cols-2; } else if (cp->Is("colorspec")) { cbits1 = (QRgb*) dummyline; cbits2 = (QRgb*) dummyline; col_lim = cols-1; } if (ap->Is("interp")) { abits1 = (QRgb*) img.scanLine(i); abits2 = (QRgb*) img.scanLine(i+1); alp_lim = cols-1; } else if (ap->Is("flat")) { abits1 = (QRgb*) img.scanLine(i); abits2 = (QRgb*) img.scanLine(i); alp_lim = cols-2; } else if (ap->Is("scalar")) { abits1 = (QRgb*) dummyline; abits2 = (QRgb*) dummyline; alp_lim = cols-1; } std::vector linequads; for (int j=0;jIs("colorspec") || ap->Is("scalar")) delete[] dummyline; return retval; } void HandleSurface::PaintMe(RenderEngine& gc) { UpdateState(); if (StringCheck("visible","off")) return; // Get the x,y,z & color data points Array xdata(ArrayPropertyLookup("xdata")); xdata.promoteType(FM_DOUBLE); Array ydata(ArrayPropertyLookup("ydata")); ydata.promoteType(FM_DOUBLE); Array zdata(ArrayPropertyLookup("zdata")); zdata.promoteType(FM_DOUBLE); if (zdata.isEmpty()) return; double *xdp = (double*) xdata.getDataPointer(); double *ydp = (double*) ydata.getDataPointer(); double *zdp = (double*) zdata.getDataPointer(); int rows = zdata.rows(); int cols = zdata.columns(); // There are many render styles... // edgealpha, edgecolor, facealpha, facecolor // facecolor // Texture mapping not supported yet if (StringCheck("facecolor","texturemap")) return; if (StringCheck("facealpha","texturemap")) return; // A quadstrip is defined by its std::vector > surfquads(BuildQuadsNoTexMap((HPConstrainedStringColor*) LookupProperty("facecolor"), (HPConstrainedStringScalar*) LookupProperty("facealpha"))); std::vector > edgequads(BuildQuadsNoTexMap((HPConstrainedStringColor*) LookupProperty("edgecolor"), (HPConstrainedStringScalar*) LookupProperty("edgealpha"))); gc.quadStrips(surfquads,StringCheck("facecolor","flat"), edgequads,StringCheck("edgecolor","flat")); #if 0 HPAutoFlatColor *ec = (HPAutoFlatColor*) LookupProperty("markeredgecolor"); HPAutoFlatColor *fc = (HPAutoFlatColor*) LookupProperty("markerfacecolor"); std::vector edgecolor; std::vector facecolor; if (ec->Is("colorspec")) edgecolor = ec->ColorSpec(); else edgecolor.push_back(-1); if (fc->Is("colorspec")) facecolor = fc->ColorSpec(); else facecolor.push_back(-1); RenderEngine::SymbolType typ = StringToSymbol(StringPropertyLookup("marker")); double sze = ScalarPropertyLookup("markersize")/2.0; // Make sure there's something to draw... if ((typ != RenderEngine::None) || (edgecolor[0] != -1) || (facecolor[0] != -1)) { // Calculate the u/v coordinates (pixels) std::vector uc; std::vector vc; std::vector zc; for (int i=0;i