// -*- C++ -*-
// $RCSfile: output.C,v $
// $Revision: 1.5 $
// $Author: langer $
// $Date: 2000/10/30 19:23:28 $
/* This software was produced by NIST, an agency of the U.S. government,
* and by statute is not subject to copyright in the United States.
* Recipients of this software assume all responsibilities associated
* with its operation, modification and maintenance. However, to
* facilitate maintenance we ask that before distributing modifed
* versions of this software, you first contact the authors at
* oof_manager@ctcms.nist.gov.
*/
#include "goof.h"
#include "pixelgroups.h"
#include "material.h"
#include "menuDef.h"
#include "output.h"
#include "ppm2oof.h"
#include "readbinary.h"
void endlist(FILE *f) { fprintf(f, "%d\n", -1); }
const int OutputFlags::end_marker = -1;
const int OutputFlags::xy_node = 0;
const char OutputFlags::no_displacement = 0;
static void do_output(const ImageRect&, const CharString&);
static void printgoofheader(const Goof *goof, FILE *file);
static int nodeno(const int x, const int y, const ImageRect &rect) {
return (rect.width()+1) * (y-rect.ymin) + x - rect.xmin;
}
// ------------------------------------------------ //
class goof_element {
private:
int id;
int s1;
int s2;
int s3;
const Material *material;
public:
goof_element(const Material *mat, int ii, int side1, int side2, int side3)
: id(ii), s1(side1), s2(side2), s3(side3), material(mat)
{
}
int compare(const Material *mat,
int side1, int side2, int side3) const
{
return (*material == *mat && s1 == side1 && s2 == side2 && s3 == side3);
}
int which() const {
return id;
}
};
// ------------------------------------------------ //
SubRegionOutputCmd::SubRegionOutputCmd()
: CommandM("subregion", "write an oof file"),
filename("out.goof")
{
AddArgument(this, "filename", filename);
AddArgument(this, "xmin", c1.x);
AddArgument(this, "xmax", c2.x);
AddArgument(this, "ymin", c1.y);
AddArgument(this, "ymax", c2.y);
c1.x = c1.y = 0;
if(current_goof) {
c2.x = current_goof->query_width();
c2.y = current_goof->query_height();
}
else
c2.x = c2.y = 0;
}
CommandFn SubRegionOutputCmd::func() {
if(!goofinit()) return;
do_output(ImageRect(c1, c2), filename);
}
CommandFn OutputCmd::func() {
if(!goofinit()) return;
do_output(current_goof->entirety(), filename);
}
static void do_output(const ImageRect &rect, const CharString &filename) {
FILE *fip;
int i, j;
if(rect.xmin < 0 || rect.ymin < 0 || rect.xmax > current_goof->query_width()
|| rect.ymax > current_goof->query_height()) {
garcon()->msout << ms_error << "rectangle is too big!" << endl << ms_normal;
return;
}
Cell_coordinate pixel;
// check to see if default material is set, if necessary.
if(!defaultmaterial) {
ArrayIterator iter(rect, ARI_EXCLUSIVE);
while(iter(pixel))
if(!current_goof->material[pixel]) {
garcon()->msout << ms_error << "No default material type!"
<< endl << ms_normal;
return;
}
}
if(use_stdout)
fip = stdout;
else
{
if ( !(fip = fopen(filename,"w")))
{
garcon()->msout << ms_error << "Could not open file for writing: "
<< filename << endl << ms_normal;
return;
}
}
printgoofheader(current_goof, fip);
// nodes
float dx = physical_width/current_goof->query_width();
ArrayIterator iter2(rect, ARI_INCLUSIVE);
while(iter2(pixel)) {
writebinary(fip,OutputFlags::xy_node);
writebinary(fip,OutputFlags::no_displacement);
writebinary(fip,nodeno(pixel.x, pixel.y, rect));
writebinary(fip, dx*pixel.x);
writebinary(fip, dx*pixel.y);
}
writebinary(fip,OutputFlags::end_marker);
// elements
Vec<goof_element*> unique_elements;
ArrayIterator iter3(rect, ARI_EXCLUSIVE);
int recycled = 0;
int count = 0;
while(iter3(pixel)) {
int ix = pixel.x;
int iy = pixel.y;
Material *material = current_goof->material[pixel];
if(!material) material = defaultmaterial;
int ilook;
for (ilook = 0; bluebox && ilook < unique_elements.capacity() &&
!unique_elements[ilook]->compare(material,2,1,1) ;
ilook++);
unsigned char flag = 0;
if(bluebox && ilook < unique_elements.capacity()) {
material->output(fip, flag,
nodeno(ix, iy, rect),
nodeno(ix+1, iy+1, rect),
nodeno(ix, iy+1, rect),
unique_elements[ilook]->which());
recycled++;
/*
cerr << "Recycling " << ix << "," << iy << " "
<< ix+1 << "," << iy+1 << " "
<< ix << "," << iy+1 << " same as "
<< unique_elements[ilook]->which() <<endl;
*/
}
else {
unique_elements.grow(1, new goof_element(material,count,2,1,1));
material->output(fip, flag,
nodeno(ix, iy, rect),
nodeno(ix+1, iy+1, rect),
nodeno(ix, iy+1, rect));
/*
cerr << endl << "Initiating " << ix << "," << iy << " "
<< ix+1 << "," << iy+1 << " "
<< ix << "," << iy+1 << " as "
<< unique_elements[ilook]->which() << endl;
*/
}
count++;
for (ilook = 0; bluebox && ilook < unique_elements.capacity() &&
!unique_elements[ilook]->compare(material,1,1,2) ;
ilook++);
flag = 0;
if(bluebox && ilook < unique_elements.capacity() ) {
material->output(fip, flag,
nodeno(ix, iy, rect),
nodeno(ix+1, iy, rect),
nodeno(ix+1, iy+1, rect),
unique_elements[ilook]->which());
/*
cerr << "Recycling " << ix << "," << iy << " "
<< ix+1 << "," << iy << " "
<< ix+1 << "," << iy+1 << " same as "
<< unique_elements[ilook]->which() <<endl;
*/
recycled++;
}
else {
unique_elements.grow(1, new goof_element(material,count,1,1,2));
material->output(fip, flag,
nodeno(ix, iy, rect),
nodeno(ix+1, iy, rect),
nodeno(ix+1, iy+1, rect));
/*
cerr << endl << "Initiating " << ix << "," << iy << " "
<< ix+1 << "," << iy << " "
<< ix+1 << "," << iy+1 << " as "
<< unique_elements[ilook]->which() << endl;
*/
}
count++;
}
garcon()->msout << ms_info << "Recycled " << recycled << " elements."
<< endl << ms_normal;
writebinary(fip,OutputFlags::end_marker);
for(i=0; i<unique_elements.capacity(); i++)
delete unique_elements[i];
// node groups
// right
for(i = rect.ymin ; i <= rect.ymax ; i++)
writebinary(fip, nodeno(rect.xmax, i, rect));
writebinary(fip,OutputFlags::end_marker);
// left
for(i = rect.ymin ; i <= rect.ymax ; i++)
writebinary(fip,nodeno(rect.xmin, i, rect));
writebinary(fip,OutputFlags::end_marker);
for(i = rect.xmin ; i <= rect.xmax ; i++)
writebinary(fip,nodeno(i, rect.ymax, rect));
writebinary(fip,OutputFlags::end_marker);
for(i = rect.xmin ; i <= rect.xmax ; i++)
writebinary(fip,nodeno(i, rect.ymin, rect));
writebinary(fip,OutputFlags::end_marker);
// upperleft
writebinary(fip, nodeno(rect.xmin, rect.ymax, rect));
writebinary(fip,OutputFlags::end_marker);
// lowerleft
writebinary(fip, nodeno(rect.xmin, rect.ymin, rect));
writebinary(fip,OutputFlags::end_marker);
// upperright
writebinary(fip, nodeno(rect.xmax, rect.ymax, rect));
writebinary(fip,OutputFlags::end_marker);
// lowerright
writebinary(fip, nodeno(rect.xmax, rect.ymin, rect));
writebinary(fip,OutputFlags::end_marker);
// element groups
for (i = 0; i < current_goof->grouplist.capacity(); i++) {
PixelGroup *cg = current_goof->grouplist[i];
cg->weed();
count = 0;
for(j = 0; j < cg->size(); j++) {
Cell_coordinate cc = (*cg)[j];
if(rect.contains(cc)) {
int id = 2*(rect.width()*(cc.y - rect.ymin) + cc.x-rect.xmin);
writebinary(fip,id);
writebinary(fip,id+1);
count++;
}
}
writebinary(fip,OutputFlags::end_marker);
garcon()->msout << ms_info << "Wrote " << 2*count << " elements in group \""
<< cg->query_name() << "\"" << endl << ms_normal;
}
if(fip != stdout)
fclose(fip);
return;
}
// there is a slightly different version of this in adaptmesh.C
static void printgoofheader(const Goof *goof, FILE *file) {
int i;
#ifdef THERMAL
fputs("program = thermal_oof\n", file);
#else // !THERMAL
fputs("program = oof\n", file);
#endif // THERMAL
fprintf(file,"version number = 5\n");
fprintf(file, "Nelements = %d\n", 2*goof->query_height()*goof->query_width());
fprintf(file, "Nnodes = %d\n",
(goof->query_width()+1)*(goof->query_height()+1));
fprintf(file,"type = b\n");
fprintf(file,"elements\n");
Vec<MaterialTypeRegistration*> ®istry = material_registry();
for(i=0; i<registry.capacity(); i++) {
fprintf(file,"%s\n",registry[i]->name().charstar());
}
endlist(file);
fprintf(file,"nodes\n");
fprintf(file,"xy\n");
endlist(file);
fprintf(file,"nodegroups\n");
fprintf(file,"right\n");
fprintf(file,"left\n");
fprintf(file,"top\n");
fprintf(file,"bottom\n");
fprintf(file,"upperleft\n");
fprintf(file,"lowerleft\n");
fprintf(file,"upperright\n");
fprintf(file,"lowerright\n");
endlist(file);
if(goof->grouplist.capacity() > 0) {
fprintf(file, "elementgroups\n");
for(i = 0; i < goof->grouplist.capacity();i++)
fprintf(file,"%s\n",goof->grouplist[i]->query_name().charstar());
endlist(file);
}
endlist(file);
}
syntax highlighted by Code2HTML, v. 0.9.1