/*
Visbuik Script
Sander Mulders
(c)2006
XXL-Workshop
*/


proc visBuik() {
	
	if ( `window -exists visBuikUI` ) {
	    deleteUI visBuikUI; // window verwijderen als deze al bestaat
	}

	window -t "visBuik constructie Creator" -widthHeight 500 500 visBuikUI;

	columnLayout -rowSpacing 6 -columnWidth 500;
	
	rowLayout -numberOfColumns 1;
	separator -w 500;
	setParent ..;
	
	rowLayout -numberOfColumns 1;
	text -l "Global Dimensions";
	setParent ..;

	rowLayout -numberOfColumns 1;
	intSliderGrp -l "Number of beams:" -field true -minValue 1 -fieldMinValue 1 -value 10  numBeams;
	setParent ..;

	
	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Concave Curve Ratio 1:" -pre 0 -field true -minValue 1 -fieldMinValue 1 -fieldMaxValue 30.00 -value 10  ratioConcave;
	setParent ..;
	
	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Convex Curve Ratio 1:" -pre 0 -field true -minValue 1  -fieldMinValue 1 -fieldMaxValue 30.00 -value 15  ratioConvex;
	setParent ..;
	
	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Offset from top mountingpoints:" -pre 2 -field true -minValue 0  -fieldMinValue 0 -fieldMaxValue 5.00 -value 1.0  offsetTop;
	setParent ..;

	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Curvature top surface % of length" -pre 2 -field true -minValue 0  -fieldMinValue 0 -fieldMaxValue 5.00 -value 2.0  curveSurface;
	setParent ..;
	
	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Max distance between vertical stands" -pre 2 -field true -minValue 0  -fieldMinValue 0 -fieldMaxValue 5.00 -value 2.1  distanceStands;
	setParent ..;

	/*rowLayout -numberOfColumns 2 -columnWidth2 130 200 ;
	button -label "Use selected curves" -command "selCurves()";
	textFieldGrp -l "curve:" -enable 0 -text "" -cw2 60 190 selectedCurves;
	setParent ..;*/
	
	rowLayout -numberOfColumns 1;
	separator -w 400;
	setParent ..;

	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Radius wire" -pre 2 -field true -minValue 0  -maxValue 1.00 -fieldMinValue 0 -fieldMaxValue 1.00 -value 0  wireRadius;
	setParent ..;
	
	rowLayout -numberOfColumns 1;
	floatSliderGrp -l "Radius stands" -pre 2 -field true -minValue 0 -maxValue 1.00 -fieldMinValue 0 -fieldMaxValue 1.00 -value 0  standsRadius;
	setParent ..;

	
	rowLayout -numberOfColumns 1 -columnAlign1 "center";
	button -label "Create" -w 400 -align "center" -command "createVisBuik()";
	setParent ..; 
		

showWindow visBuikUI;
	
}

global proc selCurves() {


	string $sl[] = `ls -sl`;
	string $curves[] = $sl;
	
	string $objType;
	string $shapes[];
	int $i = 0;


	for ($curve in $curves) {
		$shapes = `listRelatives -children -shapes $curve`;
		$objType = `objectType $shapes[0]`;
		
		if ( $objType == "nurbsCurve" ) {
			$selectedCurves[$i] = $curve;
			$i++;
		} else {
			error("No curve selected");
		}
	}
	
}


global proc createVisBuik() {
	string $selectedCurve; // Selected Curve
	float $ratioConcave = `floatSliderGrp -q -value ratioConcave`;
	float $ratioConvex = `floatSliderGrp -q -value ratioConvex`;
	float $offsetTop = `floatSliderGrp -q -value offsetTop`;
	float $curveSurface = `floatSliderGrp -q -value curveSurface`;
	float $distanceStands = `floatSliderGrp -q -value distanceStands`;
	float $wireRadius = `floatSliderGrp -q -value wireRadius`;
	float $standsRadius = `floatSliderGrp -q -value standsRadius`;


	float $startPos[];
	float $centerPos[];
	float $endPos[];
	string $circle[];
	float $curvePos[];
	string $vertCurveFinal[]; // array with the final vertical curves

	// Get selected curves
	
	string $sl[] = `ls -sl`;
	string $curves[] = $sl;
	
	string $objType;
	string $shapes[];
	int $i = 0;

	string $selectedCurves[];

	for ($curve in $curves) {
		$shapes = `listRelatives -children -shapes $curve`;
		$objType = `objectType $shapes[0]`;
		
		if ( $objType == "nurbsCurve" ) {
			$selectedCurves[$i] = $curve;
			$i++;
		} else {
			error("Selected is not a curve");
		}
	}
	
	$spanCurves = createSpans($selectedCurves);
	
	
	for ($selectedCurve in $spanCurves) {
		
		// Measure Length of base curve
		float $curveLength = `arclen $selectedCurve`;
		
		// Find centerpoint of base curve
		int $degree; // current degree of the curve
		$degree = `getAttr ($selectedCurve+".degree")`;
		
		rebuildCurve -replaceOriginal 1 -end 1 -degree $degree -keepRange 0 -keepControlPoints 1 $selectedCurve;
	
		$centerPos = `pointOnCurve -position -pr 0.5 $selectedCurve`;
	
		//start and end point of the base curve
		$startPos = `pointOnCurve -position -pr 0 $selectedCurve`;
		$endPos = `pointOnCurve -position -pr 1 $selectedCurve`;
		
		// Draw concave curve
		float $concaveDist = $curveLength/$ratioConcave;
		vector $pointsCurve[];
		$pointsCurve[0] = <<$startPos[0],$startPos[1],$startPos[2]>>;
		$pointsCurve[1] = <<$centerPos[0],($centerPos[1] - $concaveDist),$centerPos[2]>>;
		$pointsCurve[2] = <<$endPos[0],$endPos[1],$endPos[2]>>;
	
		string $curveConcave = generateGridCurve ($pointsCurve, 3); 
		
		// Draw convex curve
		float $convexDist = $curveLength/$ratioConvex;
		vector $pointsCurve[];
		$pointsCurve[0] = <<$startPos[0],($startPos[1] - $convexDist),$startPos[2]>>;
		$pointsCurve[1] = <<$centerPos[0],$centerPos[1],$centerPos[2]>>;
		$pointsCurve[2] = <<$endPos[0],($endPos[1] - $convexDist),$endPos[2]>>;
	
		string $curveConvex = generateGridCurve ($pointsCurve, 3); 
		
		// Draw the surface curve
		float $surfaceDist = $curveLength * ($curveSurface/100);
		vector $pointsCurve[];
		$pointsCurve[0] = <<$startPos[0],($startPos[1] + $offsetTop),$startPos[2]>>;
		$pointsCurve[1] = <<$centerPos[0],($centerPos[1] +$offsetTop + $surfaceDist),$centerPos[2]>>;
		$pointsCurve[2] = <<$endPos[0],($endPos[1] + $offsetTop),$endPos[2]>>;
	
		string $curveTopSurface = generateGridCurve ($pointsCurve, 3); 
	
		// Draw the vertical stands
		// start to work from the center and work from there
		
		vector $vertPoints[];
		$vertPoints[0] = <<$centerPos[0],$centerPos[1],$centerPos[2]>>;
	
		// maximum stands
		int $maximum = ($curveLength/$distanceStands)/2 + 1;
		
		int $k = 1; 
		
		for($j = 1; $j <= $maximum; $j++) {
		
			// create a circle to use as a point-finder
			
			$circle = `circle -nrx 0 -nry 1 -nrz 0 -r ($distanceStands * $j)`;
			move $centerPos[0] $centerPos[1] $centerPos[2] $circle[0];
			
			//intersect
			string $node = `curveIntersect -ch on $circle[0] $selectedCurve`;
			// get intersection points on the curve
			
			float $p2[] = `getAttr ($node + ".parameter2")`;
			
			if ($p2[0] != 0 ) {
			
				
				$curvePos = `pointOnCurve -position -pr $p2[0] $selectedCurve`;
				$vertPoints[$k] = <<$curvePos[0],$curvePos[1],$curvePos[2]>>;
				
				$k++;
				
				$curvePos = `pointOnCurve -position -pr $p2[1] $selectedCurve`;
				$vertPoints[$k] = <<$curvePos[0],$curvePos[1],$curvePos[2]>>;
				
				$k++;
			
			} 
			delete $circle;
				
		}
	
		int $z= 0;
	
		for ( $vrtPnt in $vertPoints) {
			
			string $strPnts1 = "";	
			string $strPnts2 = "";	
		
			$strPnts1 += (" -p "+$vrtPnt.x+" "+($vrtPnt.y-50)+" "+$vrtPnt.z);
			$strPnts2 += (" -p "+$vrtPnt.x+" "+($vrtPnt.y+50)+" "+$vrtPnt.z);
				
			$curveVertTemp = eval("curve -d 1 "+$strPnts1+" "+$strPnts2);
			
			string $node = `curveIntersect -ch on $curveConcave $curveVertTemp`;
			// get intersection points on the curve
			float $p2[] = `getAttr ($node + ".parameter2")`;
			float $concavePoint = $p2[0];
			
			string $node = `curveIntersect -ch on $curveConvex $curveVertTemp`;
			// get intersection points on the curve
			float $p2[] = `getAttr ($node + ".parameter2")`;
			float $convexPoint = $p2[0];
		
			string $node = `curveIntersect -ch on $curveTopSurface $curveVertTemp`;
			// get intersection points on the curve
			float $p2[] = `getAttr ($node + ".parameter2")`;
			float $surfacePoint = $p2[0];
		
		
			
			if ($concavePoint < $convexPoint) {
		
				$point1Pos = `pointOnCurve -position -pr $concavePoint $curveVertTemp`;
				$point2Pos = `pointOnCurve -position -pr $surfacePoint $curveVertTemp`;
			
				$vertCurveFinal[$z] = `curve -d 1 -p $point1Pos[0] $point1Pos[1] $point1Pos[2] -p $point2Pos[0] $point2Pos[1] $point2Pos[2]`;
		
				delete $curveVertTemp;
		
				$z++;
		
			} else {
		
				$point1Pos = `pointOnCurve -position -pr $convexPoint $curveVertTemp`;
		
				$point2Pos = `pointOnCurve -position -pr $surfacePoint $curveVertTemp`;
			
				$vertCurveFinal[$z] = `curve -d 1 -p $point1Pos[0] $point1Pos[1] $point1Pos[2] -p $point2Pos[0] $point2Pos[1] $point2Pos[2]`;
		
				delete $curveVertTemp;
		
				$z++;
			}
		}
		
		if ($wireRadius != 0) {
			extrudeTube( $curveConvex, $wireRadius);
		}
		
		if ($wireRadius != 0) {
			extrudeTube( $curveConcave, $wireRadius);
		}
		
		for ($vertCurve in $vertCurveFinal) {
			if ($wireRadius != 0) {
				extrudeTube( $vertCurve, $standsRadius);
			}
		}
	}
	
}

proc string generateGridCurve ( vector $points[], int $degree ) {
	/* generates a 1st or 3rd degree EP curve throught the points given in the array
	 * on third degree curves, two points are inserted at the beginning an end for curve direction
	 * those two points are in between the first and second point, and between the second-to-last and last point
	 */
	
	if ( $degree != 1 && $degree != 3 ) {
		error("Function generateGridCurve() is not designed to make other than 1st and 3rd degree curves");	
	}
	
	vector $pnt;
	vector $extrapnt;
	vector $interpnt;
	string $objname;
	string $stringPoints = "";
	int $i = 0;
	int $k;
	
	for ( $pnt in $points ) {
		
		$stringPoints += (" -p "+$pnt.x+" "+$pnt.y+" "+$pnt.z);
		
		/* Handle extra points for curvedirection at start/end */
		if ( $degree == 3 && $i == 0 ) {
			/* insert a point at beginning for curve direction */
			$extrapnt = $points[1];
			$interpnt = ($pnt + ($extrapnt - $pnt)/2);
			
			$stringPoints += (" -p "+$interpnt.x+" "+$interpnt.y+" "+$interpnt.z);
		}
		
		if ( $degree == 3 && $i == (size($points)-2)) {
			/* insert a point at end for curve direction */
			$extrapnt = $points[(size($points)-1)];
			$interpnt = ($pnt + ($extrapnt - $pnt)/2);
			
			$stringPoints += (" -p "+$interpnt.x+" "+$interpnt.y+" "+$interpnt.z);
		}
		if ( $degree == 3 && $i == (size($points)-2)) {
			/* insert a point at end for curve direction */
			$extrapnt = $points[(size($points)-1)];
			$interpnt = ($pnt + ($extrapnt - $pnt)/2);
			
			$stringPoints += (" -p "+$interpnt.x+" "+$interpnt.y+" "+$interpnt.z);
		}
		
		$i++;
	}

	$objname = eval("curve -d "+$degree+" "+$stringPoints);
	return $objname;
}

// script om de horizontalen te maken tussen 2 lijnen
global proc string[] createSpans(string $curves[]) {
	
	int $aantal = `intSliderGrp -q -value numBeams`;

	string $lijn[];
	int $y = 0;
	  string $curve1 = $curves[0];
	  string $curve2 = $curves[1];
	  
	  
	  rebuildCurveZeroToOne($curve1);
	  rebuildCurveZeroToOne($curve2);
	  
	  float $curvePoints[] = parameterDivision($aantal+1);
	  
	  for ( $parameter in $curvePoints) {
		  // achterhaal de world-coordinaten van de punten op elk van de drie curves
		$pos1 = `pointOnCurve -position -pr $parameter $curve1`;
		$pos2 = `pointOnCurve -position -pr $parameter $curve2`;
		
		float $op11 = $pos1[0];
		float $op21 = $pos2[0];
		
		print $op11;
		print $op21;
		
		if ( ($op11==$op21)  ) {
			print $pos1;
			print $pos2;
		} else {
			// teken een lijn tussen pos1 en pos 2
			$lijn[$y] = `curve -degree 1 -p $pos1[0] $pos1[1] $pos1[2] -p $pos2[0] $pos2[1] $pos2[2]`;
			$y++;
		}
		
 	}
	return $lijn;
}

proc rebuildCurveZeroToOne ( string $object ) {
	
	int $degree;
	$degree = `getAttr ($object+".degree")`;
	
	rebuildCurve -replaceOriginal 1 -end 1 -degree $degree -keepRange 0 -keepControlPoints 1 $object;
}


proc float[] parameterDivision ( int $numspans ) {
	float $distance = 1 / float($numspans);	
	float $pos = 0;
	float $result[];
	int $num = 0;
	
	while ( $pos <= 1 ) {
		$result[$num] = $pos;
		$num++;
		$pos = $num * $distance;
	}
	return $result;
}

global proc extrudeTube( string $path, float $mainTubeSize) {
	string $name[];
	$name = `circle -r $mainTubeSize`;
	extrude -ch true -rn false -po 0 -et 2 -ucp 1 -fpt 1 -upn 1 -rotation 0 -scale 1 -rsp 1 $name[0] $path;
	delete $name[0];
	return;
}


	