// =========================================================================== // Copyright 2018 Autodesk, Inc. All rights reserved. // // Use of this software is subject to the terms of the Autodesk license // agreement provided at the time of installation or download, or which // otherwise accompanies this software in either electronic or hard copy form. // =========================================================================== // // // Creation Date: April 22, 1998 // // Description: // The cutCurvePreset() procedure cuts // a pair of curves where they intersect using the option vars. // // Input Arguments: // None. // // Return Value: // None. // proc float getCurveStartParm( string $crv ) { string $reg = "\\[.*\\]"; float $startParm = 0.0; string $startU[] = `ls ($crv + ".un[0.0]")`; if( size($startU) > 0 ) { string $startP = match( $reg, $startU[0] ); $startParm = substring($startP, 2, size($startP)-1); } return $startParm; } proc float getCurveEndParm( string $crv ) { string $reg = "\\[.*\\]"; float $endParm = 0.0; string $endU[] = `ls ($crv + ".un[1.0]")`; if( size($endU) > 0 ) { string $endP = match( $reg, $endU[0] ); $endParm = substring($endP, 2, size($endP)-1); } return $endParm; } ///////////////////////////////////////////////////////////////////// // Description: // This proc puts together and returns a "detachCurve" command // based on the given parameter values. // proc string getDetachCmd( string $crvName, float $params[], int $replaceOriginal, int $keep[], int $ch ) { string $detachCmd = "detachCurve "; int $numParams = size($params); for( $i = 0; $i < $numParams; $i ++ ) { $detachCmd += " -p "; $detachCmd += $params[$i]; } int $numKeep = size($keep); if( $numKeep == $numParams + 1 ) { for( $i = 0; $i < $numKeep; $i ++ ) { $detachCmd += " -k "; $detachCmd += $keep[$i]; } } $detachCmd += " -ch "; $detachCmd += $ch; $detachCmd += " -rpo "; $detachCmd += $replaceOriginal; $detachCmd += " "; $detachCmd += $crvName; $detachCmd += ";"; return $detachCmd; } ///////////////////////////////////////////////////////////////////// // Description: // Returns the curve name and its list of parameter values from // $crvPts, which must be a string of the form: // "curve1.u[0.3] curve1.u[0.5] curve1.u[0.9]" // proc string parseParameters( string $crvPts, float $parms[] ) { string $crvName; string $regularExpr = "\\.u\\[.*\\]"; int $strLen; // Get the curve name // string $crv[]; tokenize $crvPts "\\." $crv; $crvName = $crv[0]; // Get a list of the selected parameter values on this curve. // tokenize will parse the string into a list of strings: // "curve1.u", "0.3", "curve1.u", "0.5", "curve1.u", "0.9" // Pull out every other one to get a list of parameters. // int $p; string $params[]; int $numParms = `tokenize $crvPts "[]" $params`; for( $p = 0; $p < $numParms; $p ++ ) { if( $p % 2 == 1 ) { $parms[size($parms)] = $params[$p]; } } return $crvName; } //----------------------------------------------------------------------------- // Cutting functionality //----------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////// // Description: // Find the longest curve segment and return a set of keep values. // 1 - means keep segment, 0 - means discard segment // There should be n+1 keep values for n cut parameter values. // proc int[] getKeepValuesForLongest( string $crv, float $cutParms[] ) { int $keepValues[]; int $numParms = size( $cutParms ); if( $numParms == 0 ) return $keepValues; string $reg = "\\[.*\\]"; // Get the start and end parameters string $startU[] = `ls ($crv + ".un[0.0]")`; if( size($startU) > 0 ) { // Get the start parameter string $startP = match( $reg, $startU[0] ); float $startParm = substring($startP, 2, size($startP)-1); // Get the end parameter string $endU[] = `ls ($crv + ".un[1.0]")`; string $endP = match( $reg, $endU[0] ); float $endParm = substring($endP, 2, size($endP)-1); // Go through each pair of parameters // startParm to $cutParms[0] // $cutParms[0] to $cutParms[1] // $cutParms[1] to $cutParms[2] // .... // $cutParms[n] to endParm // // Get the longest piece using arclen // float $len = `arclen curve1.u[0.0:0.5]`; // float $longestLen = 0.0; int $longestIndex = 0; float $p1 = $startParm; float $p2 = $startParm; for( $i = -1; $i < $numParms; $i ++ ) { if( $i == -1 ) { // startParm to $cutParms[0] $p1 = $startParm; $p2 = $cutParms[0]; } else if( $i == ($numParms-1) ) { // $cutParms[n] to endParm $p1 = $cutParms[$i]; $p2 = $endParm; } else { // $cutParms[i] to $cutParms[i+1] $p1 = $cutParms[$i]; $p2 = $cutParms[$i+1] ; } float $len; if( $p1 >= $p2 ) { $len = 0.0; } else { $len = `arclen ($crv + ".u[" + $p1 + ":" + $p2 + "]")`; } if( $len > $longestLen ) { $longestLen = $len; $longestIndex = $i; } $keepValues[$i+1] = 0; // use this to initialize all keep values to 0 } // Set the longest piece's index to 1 // $keepValues[$longestIndex+1] = 1; } return $keepValues; } ///////////////////////////////////////////////////////////////////// // Description: // Given a list of parameters to cut at on the given curve, // and a list of curve parameter of the pieces to keep, // returns the keep values: 1 to keep, 0 to discard. // eg. curve parameter range is 0.0 to 4.0, cut parameters // are 1.0, 2.0, 3.0. Curve points are 1.1, 2.2 only. // The keep values returned are: // 0, 1, 1, 0 // Note that crvParms must be in ascending order when passed in. // proc int[] getKeepValuesForCurvePts( string $crv, float $crvParms[], float $cutParms[] ) { int $keepValues[]; int $numCutParms = size( $cutParms ); int $numCrvParms = size( $crvParms ); if( $numCutParms == 0 || $numCrvParms == 0 ) return $keepValues; string $reg = "\\[.*\\]"; // Get the start and end parameters string $startU[] = `ls ($crv + ".un[0.0]")`; if( size($startU) > 0 ) { // Get the start parameter string $startP = match( $reg, $startU[0] ); float $startParm = substring($startP, 2, size($startP)-1); // Get the end parameter string $endU[] = `ls ($crv + ".un[1.0]")`; string $endP = match( $reg, $endU[0] ); float $endParm = substring($endP, 2, size($endP)-1); // Initialize the keep values to zero // for( $i = 0; $i <= $numCutParms; $i ++ ) { $keepValues[$i] = 0; } // Go through each pair of parameters // startParm to $cutParms[0] // $cutParms[0] to $cutParms[1] // $cutParms[1] to $cutParms[2] // .... // $cutParms[n] to endParm // float $p1 = $startParm; float $p2 = $startParm; int $crvParmIndex = 0; for( $i = -1; $i < $numCutParms && $crvParmIndex < $numCrvParms; $i ++ ) { if( $i == -1 ) { // startParm to $cutParms[0] $p1 = $startParm; $p2 = $cutParms[0]; } else if( $i == ($numCutParms-1) ) { // $cutParms[n] to endParm $p1 = $cutParms[$i]; $p2 = $endParm; } else { // $cutParms[i] to $cutParms[i+1] $p1 = $cutParms[$i]; $p2 = $cutParms[$i+1] ; } // If there's a curve point within this range, // then keep this piece. // if( $crvParms[$crvParmIndex] >= $p1 ) { if( $crvParms[$crvParmIndex] <= $p2 ) { // keep this piece $keepValues[$i+1] = 1; int $keep = $i+1; } while( $crvParms[$crvParmIndex] <= $p2 && $crvParmIndex < $numCrvParms ) { $crvParmIndex ++; } } } } return $keepValues; } ///////////////////////////////////////////////////////////////////// // Description: // Takes a string array of curve points and returns a unique list of // curves. eg. curve points list is: // curve1.u[1] curve1.u[0.3] curve3.u[2] curve4.u[0] curve1.u[0] // And string array (size of 4) is returned as: // curve1 curve2 curve3 curve4 // proc string [] getCurvePtsAsCurves( string $crvPts[] ) { string $crvNames[]; string $groups[] = groupObjectsByName( $crvPts, "." ); string $tokens[]; int $i; int $numGroups = size($groups); for( $i = 0; $i < $numGroups; $i ++ ) { tokenize $groups[$i] "\\." $tokens; $crvNames[$i] = $tokens[0]; } return $crvNames; } ///////////////////////////////////////////////////////////////////// // Description: // Find parameter values in crvPts[] that match the given curve. // eg. If crvPts is: // curve1.u[1] curve1.u[0.3] curve3.u[2] curve4.u[0] curve1.u[0.0] // And crv is "curve1", then this is returned (in sorted order): // 0.0, 1.0, 0.3 // proc float[] findCurvePtsForCurve( string $crv, string $crvPts[] ) { float $parms[]; float $sortedParms[]; string $groups[] = groupObjectsByName( $crvPts, "." ); string $tokens[]; int $numGroups = size($groups); for( $i = 0; $i < $numGroups; $i ++ ) { string $matched = match( $crv, $groups[$i] ); if( size( $matched ) > 0 ) { parseParameters( $groups[$i], $parms ); } } $sortedParms = sort( $parms ); return $sortedParms; } ///////////////////////////////////////////////////////////////////// // Description: // This is the main cut procedure. If $ch is true, then keep construction // history. // If $useDir == 0, then intersect without using the direction vector. // If $useDir == 1, then intersect using the direction vector. // If $useDir == 2, then intersect with the view vector in ortho views, and // without a direction vector in the persp view. // $segmentOrKeepLongestPiece: 1 - keep longest, 2 - all, 3 - curve pts // 4 - curve pts or longest if not selected // $cutAllCurveOrCutWithLast: 1 - cut all curves with all curves. // 2 - cut all curve with last curve only // proc int cutCurves( int $ch, int $replaceOriginal, int $useDir, float $dirX, float $dirY, float $dirZ, int $segmentOrKeepLongestPiece, int $cutAllCurveOrCutWithLast, float $tolerance ) { int $errors = 0; string $selList[] = `ls -sl`; // Get list of selected curves // global int $gSelectNurbsCurvesBit; string $crvs[] = `filterExpand -ex true -sm $gSelectNurbsCurvesBit $selList`; // Get list of selected curve points // global int $gSelectCurveParmPointsBit; string $crvPts[] = `filterExpand -ex true -sm $gSelectCurveParmPointsBit $selList`; // Get any curve locators, and add them as curve points // int $numCrvs = size($crvs); string $locs[]; $locs = findSelectedCurveLocators(); if( size($locs) > 0 ) { string $additionalCrvPts[] = convertLocatorsToCurvePts( $locs ); int $i = 0; for( ; $i < size($additionalCrvPts); $i++ ) { $crvPts[$numCrvs+$i] = $additionalCrvPts[$i]; } } // Merge each curve points as a selected curve, but only if the curve is // not selected already // if( size($crvPts) > 0 ) { $numCrvs = size($crvs); string $selected[]; string $moreCrvs[] = getCurvePtsAsCurves( $crvPts ); for( $i = 0; $i < size($moreCrvs); $i++ ) { $selected = `ls -sl $moreCrvs[$i]`; if( size($selected) == 0 ) { $crvs[$numCrvs+$i] = $moreCrvs[$i]; } } } if( size($crvs) < 2 ) { string $msg = (uiRes("m_cutCurvePreset.kSelectionError")); error($msg); return $errors; } // Find all intersections // string $parms[]; string $intersectNodes[]; int $history = 0; if( $cutAllCurveOrCutWithLast == 2 ) { // find intersections of each curve with the last curve $parms = findAllIntersections( $crvs, 1, $useDir, $dirX, $dirY, $dirZ, $tolerance, 1, // 1 means sorted $history, $intersectNodes ); } else { // find intersections between all pairs of curves $parms = findAllIntersections( $crvs, size($crvs), $useDir, $dirX, $dirY, $dirZ, $tolerance, 1, // 1 means sorted $history, $intersectNodes ); } // Put together a set of detach commands // int $crv; int $j; int $g = 0; string $detachCmd[]; clear($detachCmd); int $numDetachCmds = size($crvs); if( $cutAllCurveOrCutWithLast == 2 ) { $numDetachCmds --; } if( $segmentOrKeepLongestPiece == 3 && size($crvPts) == 0 ) { warning((uiRes("m_cutCurvePreset.kWarningNoCurvePointSelected")) ); $segmentOrKeepLongestPiece = 2; } else if( $segmentOrKeepLongestPiece == 4 && size($crvPts) == 0 ) { $segmentOrKeepLongestPiece = 1; } for( $c = 0; $c < $numDetachCmds; $c ++ ) { string $tok[]; float $floatParms[]; clear($floatParms); float $startParm = getCurveStartParm( $crvs[$c] ); float $endParm = getCurveEndParm( $crvs[$c] ); float $tmpParm; int $numTok = `tokenize $parms[$c] " " $tok`; for( $j = 0; $j < $numTok; $j ++ ) { if( size($tok[$j]) > 0 ) { $tmpParm = $tok[$j]; if( !(abs($tmpParm - $startParm) <= $tolerance) && !(abs($tmpParm - $endParm) <= $tolerance) ) { $floatParms[size($floatParms)] = $tok[$j]; } } } if( size($floatParms) == 0 ) { continue; } int $keep[]; if( $segmentOrKeepLongestPiece == 1 ) { // Figure out the keep values for the longest piece $keep = getKeepValuesForLongest( $crvs[$c], $floatParms ); } else if( ($segmentOrKeepLongestPiece == 3) || ($segmentOrKeepLongestPiece == 4) ) { // Figure out the keep values for the pieces with curve points float $crvPtsForCrv[] = findCurvePtsForCurve( $crvs[$c], $crvPts ); $keep = getKeepValuesForCurvePts( $crvs[$c], $crvPtsForCrv, $floatParms ); } string $detach = getDetachCmd( $crvs[$c], $floatParms, $replaceOriginal, $keep, $ch ); $detachCmd[size($detachCmd)] = $detach; clear($floatParms); } // Execute the detach commands, save all the results // string $results[]; int $numResults = 0; for( $c = 0; $c < size($detachCmd); $c ++ ) { string $res[] = eval($detachCmd[$c]); for( $i = 0; $i < size($res); $i ++ ) { $results[$numResults] = $res[$i]; $numResults ++; } } // Select all the results select -r $results; return $errors; } // Description: // "Curve intersect" with the preset options. // global proc cutCurvePreset( int $history, int $replaceOriginal, float $tolerance, int $useDirection, // 0 - off, 1 - on, 2 - use current view direction // 3 - x axis, 4 - y axis, 5 - z axis // 6 - smart mode: use view vector in ortho view // but NO direction in persp view. float $dirX, float $dirY, float $dirZ, int $segmentOrKeepLongestPiece, // 1 - keep longest, 2 - all, 3 - curve pts // 4 - curve pts, longest if not selected int $cutAllCurveOrCutWithLast ) // 1 - cut all curves with all curves. // 2 - cut all curve with last curve only { // If we're to use the "current view direction", then find out what it is. // float $viewVector[3] ; int $useDir = $useDirection; if( $useDirection == 2 ) { $viewVector = nurbsViewDirectionVector(0) ; $dirX = $viewVector[0]; $dirY = $viewVector[1]; $dirZ = $viewVector[2]; $useDir = 1; } else if( ($useDirection == 3) || ($useDirection == 4) || ($useDirection == 5)) { // Using x axis, or y axis, or z axis. So set // the $useDir argument // $useDir = 1; } else if( ($useDirection == 6) ) { $viewVector = nurbsViewDirectionVector(0) ; $dirX = $viewVector[0]; $dirY = $viewVector[1]; $dirZ = $viewVector[2]; $useDir = 2; } if( $useDir == 2 ) { // If persp view, then $useDir = 0; // If ortho view, then $useDir = 1; string $currentCamera = `lookThru -q`; if( `camera -q -o $currentCamera` ) { $useDir = 1; } else { $useDir = 0; } } if( cutCurves( $history, $replaceOriginal, $useDir, $dirX, $dirY, $dirZ, $segmentOrKeepLongestPiece, $cutAllCurveOrCutWithLast, $tolerance ) != 0 ) { string $msg = (uiRes("m_cutCurvePreset.kIntersectFailure")); error($msg); } }