Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

API - Simple Drill / Hole Function - (fromPoint3D, toPoint3D, double diameter)

22 REPLIES 22
SOLVED
Reply
Message 1 of 23
kevin
2102 Views, 22 Replies

API - Simple Drill / Hole Function - (fromPoint3D, toPoint3D, double diameter)

There needs to be a simple way to make a hole without 3D faces, sketches, features, planes, vectors, circles etc...

All a hole requires is two points and a diameter.

If I'm wrong and there is a way could someone help me in C++

22 REPLIES 22
Message 2 of 23
TrippyLighting
in reply to: kevin

@ekinsb Any chance you could help out here ?

Peter Doering
Message 3 of 23
marshaltu
in reply to: kevin

Hello,

 

A hole needs position, diameter, depth and tip angle etc. What you gave would just be to create a circle. It would be good if you can give some snapshot to demonstrate your thoughts. Then we can see if it is doable or not by API.

 

Thanks,

Marshal



Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 4 of 23
kevin
in reply to: marshaltu

My thoughts are according to basic geometry I only need two points to create a line.

Add a diameter to that and you have a hole.

This is geometrically the easiest way you can make a basic cylinder with direction.

Why is it the hardest thing to do.
Over complication can be a flaw.

 

So I've written a C++ script that Im attaching that has all the holes calculated in a stack.

The only part left is to pop them off and drill them with the saved 3D coordinates.

I just can't figure out how to make a hole 😞

Should I be using extrude instead.

I'm not opposed to hard coding a drill bit angle.

 

Attached is some napkin geometry

C++ code

Dubug console output 

 

 

2 Points w Diameter.jpg

 

#define _USE_MATH_DEFINES

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <stack>
#include <random>
#include <vector>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;
using namespace std;

Ptr<Application> app;
Ptr<UserInterface> ui;

double _poleLength = 8 * 12 * 2.54; //cm
double _gapTop = 6 * 2.54; //cm
double _gapBottom = 6 * 2.54; //cm
double _poleOD = 2 * 2.54 / 2; //cm
double _poleID = 1.5 * 2.54 / 2; //cm
double _bitL = 2.54 * 5 / 8; //cm
double _bitM = 2.54 * 1 / 2; //cm
double _bitS = 2.54 * 3 / 8; //cm
int _numHolesL = 1000;
int _numHolesM = 1000;
int _numHolesS = 1000;
double _slices = 12;
double _sliceArcLength = M_PI * _poleOD / _slices;
double _radius = _poleOD + .1; //Makes a working radius so drilling starts above pole

struct hole {
	bool real = true;
	double x, y, z, diameter = 0;
};
vector <hole> holes;

struct light {
	double x, y, z, dia, real;
};
vector <light> lights;

extern "C" XI_EXPORT bool run(const char* context)
{
	srand((unsigned)time(NULL));
	ofstream myfile;
	myfile.open("debug.txt");
	myfile << std::to_string(rand()) + " Random Initialized\n";
	myfile << M_PI << " Pi works\n";

	app = Application::get();
	if (!app)
		return false;
	myfile << "OK - Get Application\n";

	ui = app->userInterface();
	if (!ui)
		return false;
	myfile << "OK - Get User Interface\n";

	Ptr<Documents> documents = app->documents();
	if (!documents)
		return false;
	myfile << "OK - Get Documents\n";

	Ptr<Document> doc = documents->add(DocumentTypes::FusionDesignDocumentType);
	if (!doc)
		return false;
	myfile << "OK - Make Document Type Fusion Design\n";

	Ptr<Product> product = app->activeProduct();
	if (!product)
		return false;
	myfile << "OK - Select Active Product\n";

	Ptr<Design> design = product;
	if (!design)
		return false;
	myfile << "OK - Set Design to Active Product\n";

	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();
	if (!rootComp)
		return false;
	myfile << "OK - Get the root component of the active design\n";

	// Get extrude features
	Ptr<Features> feats = rootComp->features();
	if (!feats)
		return false;
	myfile << "OK - Get extrude features\n";

	Ptr<ExtrudeFeatures> extrudes = feats->extrudeFeatures();
	if (!extrudes)
		return false;
	myfile << "OK - Set Extrudes with all extrude features\n";

	// Create sketch
	Ptr<Sketches> sketches = rootComp->sketches();
	if (!sketches)
		return false;
	myfile << "OK - Create a group of sketches\n";

	Ptr<ConstructionPlane> yz = rootComp->yZConstructionPlane();
	if (!yz)
		return false;
	myfile << "OK - Set Construction Plane to YZ\n";

	Ptr<Sketch> sketch = sketches->add(yz);
	if (!sketch)
		return false;
	myfile << "OK - Add YZ plane to sketch\n";

	Ptr<SketchCurves> sketchCurves = sketch->sketchCurves();
	if (!sketchCurves)
		return false;
	myfile << "OK - Create Sketch Curves\n";

	Ptr<SketchCircles> sketchCircles = sketchCurves->sketchCircles();
	if (!sketchCircles)
		return false;
	myfile << "OK - Create Sketch Circles\n";

	Ptr<Point3D> centerPoint = Point3D::create(0, 0, 0);
	if (!centerPoint)
		return false;
	myfile << "OK - Create Center Point (0,0,0)\n";

	// Created Circles
	Ptr<SketchCircle> circle1 = sketchCircles->addByCenterRadius(centerPoint, _poleID);
	myfile << _poleID << " Inside Diameter Circle\n";
	Ptr<SketchCircle> circle2 = sketchCircles->addByCenterRadius(centerPoint, _poleOD);
	myfile << _poleOD << " Outside Diameter Circle\n";
	Ptr<Profiles> profiles = sketch->profiles();
	Ptr<Profile> outerProfile = profiles->item(1);
	myfile << "OK - Circles created\n";

	//Extrude Pole
	Ptr<ValueInput> distance = ValueInput::createByReal(_poleLength);
	if (!distance)
		return false;
	Ptr<ExtrudeFeature> extrude1 = extrudes->addSimple(outerProfile, distance, adsk::fusion::FeatureOperations::NewBodyFeatureOperation);
	if (!extrude1)
		return false;
	myfile << _poleLength << " - Extruded Pole\n";

	//Initialize Hole Variables
	hole temp;
	temp.real = true;
	double degrees = 0;
	Ptr<Point3D> tempPoint = Point3D::create(0, 0, 0);
	myfile << "OK - Hole Variables Initialized\n";

	//Vector Array Testing / Initializing
	light tempLight;
	tempLight.x = 3;
	tempLight.y = 4;
	tempLight.z = 5;
	tempLight.dia = _bitL;
	tempLight.real = true;
	myfile << "\nTest Struct\t" << tempLight.x << tempLight.y << tempLight.z << tempLight.dia << tempLight.real << "\n";
	lights.push_back(tempLight);
	myfile << "Array Size " << lights.size() << "\n";
	myfile << "Contents\t" << lights[0].x << lights[0].y << lights[0].z << lights[0].dia << lights[0].real;
	lights.pop_back();
	myfile << "\nPOP\tsize " << lights.size();

	//Test Variables
	myfile << "Test Initialized Variables\n";
	tempLight.x = _gapBottom + _bitL / 2;
	tempLight.y = cos(degrees) * _radius;
	tempLight.z = sin(degrees) * _radius;
	tempLight.dia = 1.5875;
	lights.push_back(tempLight);
	myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;
	lights.pop_back();
	myfile << "\n Brill Bits\t" << _bitL << "\t" << _bitM << "\t" << _bitS;
	myfile << "\n Pole Length & Gaps\t" << _poleLength << "\t" << _gapBottom << "\t" << _gapTop;
	myfile << "\nPoleOD\t" << _poleOD << "\tPoleID\t" << _poleID;
	myfile << "\nNum Holes\t" << _numHolesL << "\t" << _numHolesM << "\t" << _numHolesS;
	myfile << "\nSlices " << _slices << "\tArcLength " << _sliceArcLength << "\tWorkingRadius " << _radius << "\n\n";

	//Create Candy Cane
	myfile << "Candy Cane Coordinates\n";
	for (tempLight.x = _bitL / 2 + _gapBottom; tempLight.x <= _poleLength - _gapTop - _bitL; tempLight.x += _bitL * 2, degrees += 360 / 12 / 2) {
		myfile << "\nX\t" << tempLight.x;
		tempLight.y = cos(degrees) * _radius;
		tempLight.z = sin(degrees) * _radius;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;
		tempLight.y = cos(degrees + 15) * _radius;
		tempLight.z = sin(degrees + 15) * _radius;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;
		tempLight.y = cos(degrees + 30) * _radius;
		tempLight.z = sin(degrees + 30) * _radius;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;
	}

	//Create Phantom Candy Cane Holes
	myfile << "\n\nCreate Phantom Candy Cane Filer Holes\n";
	tempLight.real = false;
	double stop = (double)lights.size() - 3;
	for (int count = 0; count < stop; count += 3)
	{
		//(0)=>(1) left hole -> middle hole same row
		tempLight.x = (lights[count + 1].x - lights[count].x) / 2 + lights[count].x;
		tempLight.y = (lights[count + 1].y - lights[count].y) / 2 + lights[count].y;
		tempLight.z = (lights[count + 1].z - lights[count].z) / 2 + lights[count].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		//(0)=>(3) left hole -> uprow left
		tempLight.x = (lights[count + 3].x - lights[count].x) / 2 + lights[count].x;
		tempLight.y = (lights[count + 3].y - lights[count].y) / 2 + lights[count].y;
		tempLight.z = (lights[count + 3].z - lights[count].z) / 2 + lights[count].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		//(1)=>(3) middle hole -> uprow left
		tempLight.x = (lights[count + 3].x - lights[count + 1].x) / 2 + lights[count + 1].x;
		tempLight.y = (lights[count + 3].y - lights[count + 1].y) / 2 + lights[count + 1].y;
		tempLight.z = (lights[count + 3].z - lights[count + 1].z) / 2 + lights[count + 1].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		//(1)=>(4) middle hole -> uprow middle
		tempLight.x = (lights[count + 4].x - lights[count + 1].x) / 2 + lights[count + 1].x;
		tempLight.y = (lights[count + 4].y - lights[count + 1].y) / 2 + lights[count + 1].y;
		tempLight.z = (lights[count + 4].z - lights[count + 1].z) / 2 + lights[count + 1].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		//(1)=>(2) middle hole -> right same row
		tempLight.x = (lights[count + 2].x - lights[count + 1].x) / 2 + lights[count + 1].x;
		tempLight.y = (lights[count + 2].y - lights[count + 1].y) / 2 + lights[count + 1].y;
		tempLight.z = (lights[count + 2].z - lights[count + 1].z) / 2 + lights[count + 1].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		//(2)=>(4) right hole -> uprow middle hole
		tempLight.x = (lights[count + 4].x - lights[count + 2].x) / 2 + lights[count + 2].x;
		tempLight.y = (lights[count + 4].y - lights[count + 2].y) / 2 + lights[count + 2].y;
		tempLight.z = (lights[count + 4].z - lights[count + 2].z) / 2 + lights[count + 2].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		//(2)=>(5) right hole -> uprow right hole
		tempLight.x = (lights[count + 5].x - lights[count + 2].x) / 2 + lights[count + 2].x;
		tempLight.y = (lights[count + 5].y - lights[count + 2].y) / 2 + lights[count + 2].y;
		tempLight.z = (lights[count + 5].z - lights[count + 2].z) / 2 + lights[count + 2].z;
		lights.push_back(tempLight);
		myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

		myfile << "\n Count " << count << "\t Lights Size " << lights.size() << "\n";

		if (count < stop && count > stop -6) {
			//Fill in last row of fake holes
			myfile << "\nFill last row of fake holes";
			//(3)=>(4) up left -> up middle
			tempLight.x = (lights[count + 4].x - lights[count + 3].x) / 2 + lights[count + 3].x;
			tempLight.y = (lights[count + 4].y - lights[count + 3].y) / 2 + lights[count + 3].y;
			tempLight.z = (lights[count + 4].z - lights[count + 3].z) / 2 + lights[count + 3].z;
			lights.push_back(tempLight);
			myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;

			//(4)=>(5) up middle -> up right
			tempLight.x = (lights[count + 5].x - lights[count + 4].x) / 2 + lights[count + 4].x;
			tempLight.y = (lights[count + 5].y - lights[count + 4].y) / 2 + lights[count + 4].y;
			tempLight.z = (lights[count + 5].z - lights[count + 4].z) / 2 + lights[count + 4].z;
			lights.push_back(tempLight);
			myfile << "\n[" << lights.size() - 1 << "]\t" << lights[lights.size() - 1].x << "\t" << lights[lights.size() - 1].y << "\t" << lights[lights.size() - 1].z << "\t" << lights[lights.size() - 1].dia << "\t" << lights[lights.size() - 1].real;
			myfile << "\n Count " << count << "\t Lights Size " << lights.size() << "\n"; myfile << "\n Count " << count << "\t Lights Size " << lights.size() << "\n";
		}
	}

	//Pick The Random large Holes
	for (int temp = 0; temp < _numHolesL; temp++) {
		//Pick Random X, Y & Z 3Dpoints
		//myfile << "\nCheck out Random Temp Light Hole";
		tempLight.real = true;
		tempLight.dia = _bitL;
		degrees = rand() % 360;
		tempLight.x = (double)(rand() % (int)(_poleLength - _gapBottom - _gapTop)) + _gapBottom;
		tempLight.y = cos(degrees) * _radius;
		tempLight.z = sin(degrees) * _radius;
		myfile << "\n[temp]\t" << tempLight.x << "\t" << tempLight.y << "\t" << tempLight.z << "\t" << tempLight.dia << "\t" << tempLight.real;
		//Check random point distance to all other current points
		for (int x = 0; x < lights.size(); x++) {
			if (sqrt(pow(tempLight.x - lights[x].x, 2) + pow(tempLight.y - lights[x].y, 2) + pow(tempLight.z - lights[x].z, 2)) > _bitL*2.5) {
				lights.push_back(tempLight);
				myfile << "\n["<<lights.size()<<"][" << x << "] Degrees " << degrees << "\t" << tempLight.x << "\t" << tempLight.y << "\t" << tempLight.z << "\t" << tempLight.dia << "\t" << tempLight.real;
				break;
			}
		}
	}

	//Pick The Random Medium Holes
	for (int temp = 0; temp < _numHolesM; temp++) {
		//Pick Random X, Y & Z 3Dpoints
		//myfile << "\nCheck out Random Temp Light Hole";
		tempLight.real = true;
		tempLight.dia = _bitM;
		degrees = rand() % 360;
		tempLight.x = (double)(rand() % (int)(_poleLength - _gapBottom - _gapTop)) + _gapBottom;
		tempLight.y = cos(degrees) * _radius;
		tempLight.z = sin(degrees) * _radius;
		myfile << "\n[temp]\t" << tempLight.x << "\t" << tempLight.y << "\t" << tempLight.z << "\t" << tempLight.dia << "\t" << tempLight.real;
		//Check random point distance to all other current points
		for (int x = 0; x < lights.size(); x++) {
			if (sqrt(pow(tempLight.x - lights[x].x, 2) + pow(tempLight.y - lights[x].y, 2) + pow(tempLight.z - lights[x].z, 2)) > _bitM*2.5) {
				lights.push_back(tempLight);
				myfile << "\n[" << lights.size() << "][" << x << "] Degrees " << degrees << "\t" << tempLight.x << "\t" << tempLight.y << "\t" << tempLight.z << "\t" << tempLight.dia << "\t" << tempLight.real;
				break;
			}
		}
	}

	//Pick The Random Small Holes
	for (int temp = 0; temp < _numHolesS; temp++) {
		//Pick Random X, Y & Z 3Dpoints
		//myfile << "\nCheck out Random Temp Light Hole";
		tempLight.real = true;
		tempLight.dia = _bitS;
		degrees = rand() % 360;
		tempLight.x = (double)(rand() % (int)(_poleLength - _gapBottom - _gapTop)) + _gapBottom;
		tempLight.y = cos(degrees) * _radius;
		tempLight.z = sin(degrees) * _radius;
		myfile << "\n[temp]\t" << tempLight.x << "\t" << tempLight.y << "\t" << tempLight.z << "\t" << tempLight.dia << "\t" << tempLight.real;
		//Check random point distance to all other current points
		for (int x = 0; x < lights.size(); x++) {
			if (sqrt(pow(tempLight.x - lights[x].x, 2) + pow(tempLight.y - lights[x].y, 2) + pow(tempLight.z - lights[x].z, 2)) > _bitS*2.5) {
				lights.push_back(tempLight);
				myfile << "\n[" << lights.size() << "][" << x << "] Degrees " << degrees << "\t" << tempLight.x << "\t" << tempLight.y << "\t" << tempLight.z << "\t" << tempLight.dia << "\t" << tempLight.real;
				break;
			}
		}
	}

	/*Make Holes popping of lights array*/

	//Ending
	ui->messageBox("Hey Kevin " + std::to_string(rand()));
	return true;
	myfile.close();
}

#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN
 

Message 5 of 23
kevin
in reply to: kevin

I keep trying to make a hole, don't get errors but can't figure out why they dont appear.

 

	//See if you can make funtion hole or extrude work
	myfile << "\n Start Fusion 360 geometric variables";
	Ptr<adsk::core::Point3D> fromPoint3D = adsk::core::Point3D::create(lights[0].x, lights[0].y, lights[0].z);
	Ptr<adsk::core::Point3D> toPoint3D = adsk::core::Point3D::create(lights[0].x, 0, 0);

	Ptr<adsk::core::Line3D> straightLine = adsk::core::Line3D::create(fromPoint3D, toPoint3D);
	Ptr<adsk::core::Line3D> reverseLine = adsk::core::Line3D::create(toPoint3D, fromPoint3D);

	Ptr<adsk::core::Vector3D> fromVector3D = adsk::core::Vector3D::create(lights[0].x, lights[0].y, lights[0].z);
	Ptr<adsk::core::Vector3D> toVector3D = adsk::core::Vector3D::create(lights[0].x, 0, 0);
	
	Ptr<adsk::core::Circle3D> toCircle3D = adsk::core::Circle3D::createByCenter(fromPoint3D, toVector3D, _bitL);
	Ptr<adsk::core::Circle3D> fromCircle3D = adsk::core::Circle3D::createByCenter(fromPoint3D, fromVector3D, _bitL); //Won't work?
	
	Ptr<adsk::core::Cylinder> fromCylinder = adsk::core::Cylinder::create(fromPoint3D, fromVector3D, _bitL);
	Ptr<adsk::core::Cylinder> toCylinder = adsk::core::Cylinder::create(toPoint3D, toVector3D, _bitL); //I think its backwards
	myfile << "\n End create Geometric Variables";


	// Create a hole input
	Ptr<ConstructionPlane> xPlane = rootComp->xConstructionAxis();
	Ptr<HoleFeatures> lightHoles = feats->holeFeatures();
	Ptr<HoleFeatureInput> lightHoleInput = lightHoles->createSimpleInput(ValueInput::createByReal(_bitL));//Hole Diameter
	lightHoleInput->setDistanceExtent(ValueInput::createByReal(sqrt(pow(tempLight.x - lights[0].x, 2) + pow(tempLight.y - lights[0].y, 2) + pow(tempLight.z - lights[0].z, 2))));
	myfile << "\nDistance Extent" << ValueInput::createByReal(sqrt(pow(tempLight.x - lights[0].x, 2) + pow(tempLight.y - lights[0].y, 2) + pow(tempLight.z - lights[0].z, 2)));
	lightHoleInput->setPositionByPoint(xPlane,fromPoint3D);
	Ptr<HoleFeature> lightHole = lightHoles->add(lightHoleInput);

	lightHoleInput->setPositionAtCenter(xPlane,fromCircle3D);
	Ptr<HoleFeature> lightHole2 = lightHoles->add(lightHoleInput);
Message 6 of 23
marshaltu
in reply to: kevin

Hello,

 

It is clearer for me what you were going to do. You had have some logic to deduce the depth/tip angle of hole. I ran your codes and get the following "tube" created in Fusion 360.

 

I am not clear where you are going to create "hole"? At least you need a plane to place the "hole" on? Though you wanted to create an extrude feature and cut to get the "hole".

 

Thanks,

Marshal

 

Hole.png



Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 7 of 23
kevin
in reply to: marshaltu

I extrude the pole which is basically just stock aluminum.

All the calculations push <stack> start(x,y,z) coordinates and when drilled will stop in the middle of the pole on the x axis endPoint(x,0,0)

I can't get the drill hole part to work for ~5,000 holes.

 

Here's a picture of a short test version.

Does that help you visualize?

 

Holy.jpg

Message 8 of 23
marshaltu
in reply to: kevin

Hello,

 

Thank you for the real picture. It is clear to me.

 

I would like to give a sample how to create hole based on a point on cylinder face. I hope it can give quick idea to you and help you on your real project.

 

I assume you have had cylinder face and its diameter. And you have had a series of points which are located at the cylinder face. You can create the hole with specific diameter/depth one by one based on every point. 

 

Thanks,

Marshal

 

#Author-
#Description-

import adsk.core, adsk.fusion, traceback
import math

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        design = adsk.fusion.Design.cast(app.activeProduct)
        root = design.rootComponent
        basesketch = root.sketches.add(root.xYConstructionPlane)
        basesketch.isVisible = False
        
        # Get outside cylinder face by radius (e.g. 2.5 cm)
        cylinderface = None
        for face in root.bRepBodies.item(0).faces:
            cylindersurface = adsk.core.Cylinder.cast(face.geometry)
            if cylindersurface and math.fabs(cylindersurface.radius - 2.5) < 1.0e-6:
                cylinderface = face
                break

        # Create hole based on a point(e.g. (2.5, 0, 2.5))
        # Place the point into sketch
        pt = adsk.core.Point3D.create(2.5, 0, 2.5)
        basesketchpoint = basesketch.sketchPoints.add(pt)
        
        if cylinderface:
        
            # Firstly we have to create a work plane
            workplaneinput = root.constructionPlanes.createInput()  
            workplaneinput.setByTangentAtPoint(cylinderface, basesketchpoint)
            workplane = root.constructionPlanes.add(workplaneinput)
            
            # Create hole with specific radius(e.g. 0.5 cm) and depth (e.g. 1 cm)
            holeinput = root.features.holeFeatures.createSimpleInput(adsk.core.ValueInput.createByString('1 cm'))
            holeinput.setPositionByPoint(workplane, pt)
            holeinput.setDistanceExtent(adsk.core.ValueInput.createByReal(1))
            root.features.holeFeatures.add(holeinput)
            
            # Hide workplane
            workplane.isLightBulbOn = False
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 9 of 23
kevin
in reply to: marshaltu

OMG Marshal you've been a ton of help today.

I can extrude fine & create tangent planes.

I've spent another day and still can't figure out how to not crash Fusion when trying to set a hole point.

You can see the two commented lines towards the bottom.

Do you think you can help me get this to actually drill a hole?

I can't think of whats wrong.

I feel like I'm so close, just one line of code away & then I can put the whole thing together

 

On the main topic though. I still think a SetPositionByPoints function would be great for cases like this that automatically create the needed tangent plane in the background.

 

Snap.png

 

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;

Ptr<Application> app;
Ptr<UserInterface> ui;

extern "C" XI_EXPORT bool run(const char* context)
{
	Ptr<Application> app = Application::get();
	ui = app->userInterface();
	Ptr<Documents> docs = app->documents();

	// Create a document.
	Ptr<Document> doc = docs->add(DocumentTypes::FusionDesignDocumentType);
	Ptr<Design> design = app->activeProduct();
	
	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();

	// Create sketch
	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());

	// Create sketch circle
	Ptr<SketchCurves> curves = sketch->sketchCurves();
	Ptr<SketchCircles> circles = curves->sketchCircles();
	Ptr<Point3D> centerPoint = Point3D::create(0, 0, 0);
	circles->addByCenterRadius(centerPoint, 0.75);
	circles->addByCenterRadius(centerPoint, 1);

	// Get the profile defined by the circle
	Ptr<Profiles> profs = sketch->profiles();
	Ptr<Profile> prof = profs->item(1);

	// Create an extrusion input
	Ptr<Features> features = rootComp->features();
	Ptr<ExtrudeFeatures> extrudes = features->extrudeFeatures();
	Ptr<ExtrudeFeatureInput> extInput = extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation);

	// Define that the extent is a distance extent of 5 cm
	Ptr<ValueInput> distance = ValueInput::createByReal(5.0);

	// Set the distance extent to be one-way symmetric
	extInput->setDistanceExtent(false, distance);

	// Set the extrude to be a solid one
	extInput->isSolid(true);

	// Create an cylinder
	Ptr<ExtrudeFeature> extrude = extrudes->add(extInput);

	// Get construction planes
	Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();

	// Create construction plane input 
	Ptr<ConstructionPlaneInput> planeInput = planes->createInput();

	// Add construction plane by tangent #5
	Ptr<BRepFaces> extSideFaces = extrude->sideFaces();
	Ptr<BRepFace> cylinderFace = extSideFaces->item(1);

	extInput->setDistanceExtent(false, distance);
	planeInput->setByTangentAtPoint(cylinderFace, Point3D::create(2,0,1));
	planes->add(planeInput);

	// Create an extrusion input
	Ptr<Features> feats = rootComp->features();
	Ptr<SketchPoints> drillPoints = sketch->sketchPoints();
	Ptr<Point3D> pointFrom = Point3D::create(3, 1, 0);
	Ptr<SketchPoint> sketchPointFrom = drillPoints->add(pointFrom);
	Ptr<Point3D> pointTo = Point3D::create(3, 0, 0);
	Ptr<SketchPoint> sketchPointTo = drillPoints->add(pointTo);


	// Create a hole input
	double stroke = 1;
	Ptr<HoleFeatures> holes = feats->holeFeatures();
	Ptr<HoleFeatureInput> holeInput = holes->createSimpleInput(5/8);
	//holeInput->setPositionBySketchPoints(drillPoints);
	//holeInput->setPositionByPoint(planes, pointFrom);
	//holeInput->setDistanceExtent(adsk::core::ValueInput::createByReal(1));
	Ptr<HoleFeature> hole = holes->add(holeInput);

	return true;
}


#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN

 

 

Message 10 of 23
marshaltu
in reply to: kevin

Hello,

 

There were a couple of errors in your codes:

 

1. The tangent work plane didn't created in correct position. You have to create sketch point based on the point you plan to drill and then create tangent plane on the sketch point.

2. "5 / 8" would be equal to zero. It took me quite some time to figure the error out.

3. You can pass "planes" to create hole instead of the work plane you created based on drill point.

 

However I run into another issue which I cannot create tangent work plane because of a bug in Fusion 360 (logged as UP-38447). I show the error with "ui->messageBox("Failed to create tangent work plane by cylinder face.")". So I have to work the bug around by saving the document and reopen it. Now the following codes would be able to create a hole for it on (2, 0, 1).

 

Thanks,

Marshal

 

 

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;

Ptr<Application> app;
Ptr<UserInterface> ui;

bool createToolBody()
{
	Ptr<Documents> docs = app->documents();

	// Create a document.
	Ptr<Document> doc = docs->add(DocumentTypes::FusionDesignDocumentType);
	Ptr<Design> design = app->activeProduct();

	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();

	// Create sketch
	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());

	// Create sketch circle
	Ptr<SketchCurves> curves = sketch->sketchCurves();
	Ptr<SketchCircles> circles = curves->sketchCircles();
	Ptr<Point3D> centerPoint = Point3D::create(0, 0, 0);
	circles->addByCenterRadius(centerPoint, 0.75);
	circles->addByCenterRadius(centerPoint, 1);

	// Get the profile defined by the circle
	Ptr<Profiles> profs = sketch->profiles();
	Ptr<Profile> prof = profs->item(1);

	//// Create an extrusion input
	Ptr<Features> features = rootComp->features();
	Ptr<ExtrudeFeatures> extrudes = features->extrudeFeatures();
	Ptr<ExtrudeFeatureInput> extInput = extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation);

	// Define that the extent is a distance extent of 5 cm
	Ptr<ValueInput> distance = ValueInput::createByReal(5.0);

	// Set the distance extent to be one-way symmetric
	extInput->setDistanceExtent(false, distance);

	// Set the extrude to be a solid one
	extInput->isSolid(true);

	// Create an cylinder
	Ptr<ExtrudeFeature> extrude = extrudes->add(extInput);

	// Save and reopen the document to work a bug around.
	Ptr<ExportManager> exportMgr = design->exportManager();
	Ptr<FusionArchiveExportOptions> exportOption = exportMgr->createFusionArchiveExportOptions("C:\\temp.f3d");
	exportMgr->execute(exportOption);

	doc->close(false);

	Ptr<ImportManager> importMgr = app->importManager();
	Ptr<FusionArchiveImportOptions> importOption = importMgr->createFusionArchiveImportOptions("C:\\temp.f3d");
	importMgr->importToNewDocument(importOption);

	return true;
}

extern "C" XI_EXPORT bool run(const char* context)
{
	app = Application::get();
	ui = app->userInterface();

	if (!createToolBody())
		return false;

	Ptr<Design> design = app->activeProduct();

	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();

	// Get construction planes
	Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();

	// Create construction plane input 
	Ptr<ConstructionPlaneInput> planeInput = planes->createInput();

	// Add construction plane by tangent #5
	Ptr<BRepBodies> bodies = rootComp->bRepBodies();
	Ptr<BRepBody> body = bodies->item(0);
	Ptr<BRepFaces> faces = body->faces();
	Ptr<BRepFace> cylinderFace;
	for (auto face : faces)
	{
		Ptr<Cylinder> cylinder = face->geometry();
		if (cylinder && std::fabs(cylinder->radius() - 1) < 1.0e-6)
		{
			cylinderFace = face;
			break;
		}
	}

	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());
	Ptr<SketchPoints> points = sketch->sketchPoints();

	Ptr<Point3D> pickPt = Point3D::create(2, 0, 1);
	Ptr<SketchPoint> pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));
	planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
	Ptr<ConstructionPlane> plane = planes->add(planeInput);
	if (!plane)
	{
		ui->messageBox("Failed to create tangent work plane by cylinder face.");
		return false;
	}

	// Create a hole input
	double stroke = 1;
	Ptr<Features> features = rootComp->features();
	Ptr<HoleFeatures> holes = features->holeFeatures();
	Ptr<HoleFeatureInput> holeInput = holes->createSimpleInput(ValueInput::createByReal(5.0 / 8));
	holeInput->setPositionByPoint(plane, Point3D::create(2, 0, 1));
	holeInput->setDistanceExtent(adsk::core::ValueInput::createByReal(1));
	Ptr<HoleFeature> hole = holes->add(holeInput);

	return true;
}


#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN

 



Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 11 of 23
kevin
in reply to: marshaltu

Hi Marshall,

Wow I wouldn't have thought about any of this except.

The 5/8, I should have known better.

I've can't seem to run the code you provided.

Every time Export Manager Export Executes it crashes.

I've verified this with Visual Studio 2012 V110 & Visual Studio 2017 V141

 

ExportMgr.png

ExportMgr.png

 

Export Options.png

 

Message 12 of 23
marshaltu
in reply to: kevin

Hello,

I forgot to mention I hardcoded the path of export with "C:\\temp.f3d". You may have to change it if the path isn't available in your machine.

BTW: it would be better to check every result after call API. Sometimes you would get null object because some errors. It must make Fusion crash if you continue to use it. "Application::getLastError" can give detailed informatin when error is encountered.

Thanks,
Marshal


Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 13 of 23
kevin
in reply to: marshaltu

I saw that it was hard coded and tried several ways with no luck 😞

I don't even now the reason I'm opening and closing the document 5000's but I feel like that could crash or take an extremely long time.

The good news is. I'm finally getting these holes to work and can start adding logic 🙂

I don't know how I could have ever gotten even this far without you

I'll keep this post updated as I progress.

Also I still believe this could be a new hole function using two points and have the planes generated automatically.

 

Yes!!!.png

Message 14 of 23
BrianEkins
in reply to: kevin

Here's a totally different approach that does just what you asked about in the beginning.  It creates a bunch of cylinders using the coordinates of the ends of the cylinders and the radii.  It uses something called "Temporary B-Rep".  This is also much faster than creating standard features.  The sample code I wrote created the 2000 holes shown in the picture below in less than 20 seconds. I wrote about it in more detail here:

 

https://ekinssolutions.com/using-temporary-b-rep-in-fusion-360/

Holes.png

 

 

 

 

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
Message 15 of 23
kevin
in reply to: BrianEkins

Brian,

 

That is really cool how you did that & I almost followed it.
Just need to convert it to C++.

& Yes it took over an hour to do 400 holes & I plan around 6000 😞

Bought a new thinkpad p52s w/ Quadro card today hopefully that helps since my laptop and Quadro card is 5 years old.

I'm also going to try NVidia's grid compute virtual machine trial to see if I can brute force it since I'm so close.
Can I delete planes after I create a hole? Will that make it faster? Because its simple and beautiful.

Cuz right now I have more planes than Howard Hughes.

 

Also using a different diameter for inside and outside hole. Will that cause problems with the CAM tooling/path?
Havent gotten that far yet.

 

Planes.pngPole.png

Message 16 of 23
kevin
in reply to: kevin

Would anyone be kind enough to generate this for me.

I've finished the program and have rendered it in sections just fine.But it's just too large for my computer even running it over night and eventually crashes.

Yesterday I purchased new hardware and a quadro card but it will still take weeks to come in.

 

-Kevin

Message 17 of 23
marshaltu
in reply to: kevin

Hello,

 

The problem which export manager didn't work was invalid file path. It should be "C:\\temp.f3d". Good news is that you should not need the workaround as I made a mistake in the codes I posted. I added a sketch point to that sketch which used for creating extrude feature. It caused cylinder faces became invalid. The codes as below should work well. 

 

Regarding to performance issue, Brain suggested a better approach and maybe you could give a try. 

 

Thanks,

Marshal

 

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;

Ptr<Application> app;
Ptr<UserInterface> ui;

extern "C" XI_EXPORT bool run(const char* context)
{
	app = Application::get();
	ui = app->userInterface();

	Ptr<Documents> docs = app->documents();

	// Create a document.
	Ptr<Document> doc = docs->add(DocumentTypes::FusionDesignDocumentType);
	Ptr<Design> design = app->activeProduct();

	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();

	// Create sketch
	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());
	Ptr<SketchPoints> points = sketch->sketchPoints();

	Ptr<Point3D> pickPt = Point3D::create(2, 0, 1);
	Ptr<SketchPoint> pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));

	// Create sketch circle
	Ptr<SketchCurves> curves = sketch->sketchCurves();
	Ptr<SketchCircles> circles = curves->sketchCircles();
	Ptr<Point3D> centerPoint = Point3D::create(0, 0, 0);
	circles->addByCenterRadius(centerPoint, 0.75);
	circles->addByCenterRadius(centerPoint, 1);

	// Get the profile defined by the circle
	Ptr<Profiles> profs = sketch->profiles();
	Ptr<Profile> prof = profs->item(1);

	//// Create an extrusion input
	Ptr<Features> features = rootComp->features();
	Ptr<ExtrudeFeatures> extrudes = features->extrudeFeatures();
	Ptr<ExtrudeFeatureInput> extInput = extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation);

	// Define that the extent is a distance extent of 5 cm
	Ptr<ValueInput> distance = ValueInput::createByReal(5.0);

	// Set the distance extent to be one-way symmetric
	extInput->setDistanceExtent(false, distance);

	// Set the extrude to be a solid one
	extInput->isSolid(true);

	// Create an cylinder
	Ptr<ExtrudeFeature> extrude = extrudes->add(extInput);

	// Get construction planes
	Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();

	// Create construction plane input 
	Ptr<ConstructionPlaneInput> planeInput = planes->createInput();

	// Add construction plane by tangent #5
	Ptr<BRepFaces> faces = extrude->sideFaces();
	Ptr<BRepFace> cylinderFace;
	for (auto face : faces)
	{
		Ptr<Cylinder> cylinder = face->geometry();
		if (cylinder && std::fabs(cylinder->radius() - 1) < 1.0e-6)
		{
			cylinderFace = face;
			break;
		}
	}

	planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
	Ptr<ConstructionPlane> plane = planes->add(planeInput);
	if (!plane)
	{
		ui->messageBox("Failed to create tangent work plane by cylinder face.");
		return false;
	}

	// Create a hole input
	double stroke = 1;
	Ptr<HoleFeatures> holes = features->holeFeatures();
	Ptr<HoleFeatureInput> holeInput = holes->createSimpleInput(ValueInput::createByReal(5.0 / 8));
	holeInput->setPositionByPoint(plane, pickPt);
	holeInput->setDistanceExtent(adsk::core::ValueInput::createByReal(1));
	Ptr<HoleFeature> hole = holes->add(holeInput);

	return true;
}


#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN


Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 18 of 23
kevin
in reply to: marshaltu

I also forgot to mention that I got everything to work just be commenting out the export manager.

My problem now is rendering.

 

My computer crashes after it gets up to around 10GB of Ram while running the script.

I can generate it in parts but no all together without a GPU

Any ideas on how to run this thing?
Maybe somethings configured wrong

 

ram.pngstats.png

 

 

#define _USE_MATH_DEFINES

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <stack>
#include <random>
#include <vector>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;
using namespace std;

ofstream myfile;

struct hole {
	double x, y, z, dia;
	bool isReal;
};
vector<hole> holes;
hole temp;

double degrees = 0;

double _poleLength = 2.54 * 8 * 12;
double _gapTop = 2.54 * 6;
double _gapBottom = 2.54 * 6;
double _poleOD = 2.54 * 1;
double _poleID = 2.54 * .75;
double _slices = 12;
double _sliceArcLength = M_PI * _poleOD / _slices;
double _radius = _poleOD / 2;
double _bitL = 2.54 * 5 / 16;
double _bitM = 2.54 * 1 / 4;
double _bitS = 2.54 * 3 / 16;
int _numHolesL = 2000;
int _numHolesM = 1500;
int _numHolesS = 1000;

Ptr<Application> app = Application::get();
Ptr<UserInterface> ui = app->userInterface();

bool createToolBody()
{
	Ptr<Documents> docs = app->documents();

	// Create a document.
	Ptr<Document> doc = docs->add(DocumentTypes::FusionDesignDocumentType);
	Ptr<Design> design = app->activeProduct();

	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();

	// Create sketch
	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());

	// Create sketch circle
	Ptr<SketchCurves> curves = sketch->sketchCurves();
	Ptr<SketchCircles> circles = curves->sketchCircles();
	Ptr<Point3D> centerPoint = Point3D::create(0, 0, 0);
	circles->addByCenterRadius(centerPoint, _poleID);
	circles->addByCenterRadius(centerPoint, _poleOD);

	// Get the profile defined by the circle
	Ptr<Profiles> profs = sketch->profiles();
	Ptr<Profile> prof = profs->item(1);

	//// Create an extrusion input
	Ptr<Features> features = rootComp->features();
	Ptr<ExtrudeFeatures> extrudes = features->extrudeFeatures();
	Ptr<ExtrudeFeatureInput> extInput = extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation);

	// Define that the extent is a distance extent of 8 ft
	Ptr<ValueInput> distance = ValueInput::createByReal(_poleLength);

	// Set the distance extent to be one-way symmetric
	extInput->setDistanceExtent(false, distance);

	// Set the extrude to be a solid one
	extInput->isSolid(true);

	// Create an cylinder
	Ptr<ExtrudeFeature> extrude = extrudes->add(extInput);

	/*
	// Save and reopen the document to work a bug around.
	Ptr<ExportManager> exportMgr = design->exportManager();
	Ptr<FusionArchiveExportOptions> exportOption = exportMgr->createFusionArchiveExportOptions("C:\\temp.f3d");
	exportMgr->execute(exportOption);

	doc->close(false);

	Ptr<ImportManager> importMgr = app->importManager();
	Ptr<FusionArchiveImportOptions> importOption = importMgr->createFusionArchiveImportOptions("C:\\temp.f3d");
	importMgr->importToNewDocument(importOption);
	*/

	return true;
}

void makeCylinder() {
	Ptr<Design> design = app->activeProduct();
	Ptr<Component> rootComp = design->rootComponent();
	Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();
	Ptr<ConstructionPlaneInput> planeInput = planes->createInput();

	// Do the magic cylinder stuff
	Ptr<BRepBodies> bodies = rootComp->bRepBodies();
	Ptr<BRepBody> body = bodies->item(0);
	Ptr<BRepFaces> faces = body->faces();
	Ptr<BRepFace> cylinderFace;
	for (auto face : faces)
	{
		Ptr<Cylinder> cylinder = face->geometry();
		if (cylinder && std::fabs(cylinder->radius() - _poleOD) < 1.0e-6)
		{
			cylinderFace = face;
			break;
		}
	}

	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());
	Ptr<SketchPoints> points = sketch->sketchPoints();

	Ptr<Point3D> pickPt = Point3D::create(2, 0, 1);
	Ptr<SketchPoint> pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));
	planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
	Ptr<ConstructionPlane> plane = planes->add(planeInput);
	if (!plane)
	{
		ui->messageBox("Failed to create tangent work plane by cylinder face.");
		//return false;
	}
}


/*
void drillHole(double x, double y, double z) {

Ptr<Design> design = app->activeProduct();
Ptr<Component> rootComp = design->rootComponent();
Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();

Ptr<SketchPoints> points = sketch->sketchPoints();


//Create new plane hole
planes->createInput();
Ptr<Point3D>pickPt = Point3D::create(x, y, z);
//points->release();
Ptr<SketchPoint>pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));
planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
plane = planes->add(planeInput);
holeInput->setPositionByPoint(plane, Point3D::create(x, y, z));
holes->add(holeInput);
}
*/


void makeCandyCane(){
	//Candy Cane Coordinated
	for (temp.x = _gapBottom; temp.x <= _poleLength - _gapTop; temp.x += _bitL) {
		temp.y = cos(degrees);
		temp.z = sin(degrees);
		holes.push_back(temp);
		//holes.pop_back();
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
		temp.y = cos(degrees + .5);
		temp.z = sin(degrees + .5);
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
		temp.y = cos(degrees + 1);
		temp.z = sin(degrees + 1);
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
		temp.x += _bitL;
		degrees += .25;
	}myfile << "\nOK - Candy Cane\n";
}

void makePhantomHoles(){
	//Create Phantom Candy Cane Holes
	myfile << "Create Phantom Holes\n";
	temp.isReal = false;
	double stop = (double)holes.size() - 3;

	for (int count = 0; count < stop; count += 3)
	{
		//(0)=>(1) left hole -> middle hole same row
		temp.x = (holes[count + 1].x - holes[count].x) / 2 + holes[count].x;
		temp.y = (holes[count + 1].y - holes[count].y) / 2 + holes[count].y;
		temp.z = (holes[count + 1].z - holes[count].z) / 2 + holes[count].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(0)=>(3) left hole -> uprow left
		temp.x = (holes[count + 3].x - holes[count].x) / 2 + holes[count].x;
		temp.y = (holes[count + 3].y - holes[count].y) / 2 + holes[count].y;
		temp.z = (holes[count + 3].z - holes[count].z) / 2 + holes[count].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(1)=>(3) middle hole -> uprow left
		temp.x = (holes[count + 3].x - holes[count + 1].x) / 2 + holes[count + 1].x;
		temp.y = (holes[count + 3].y - holes[count + 1].y) / 2 + holes[count + 1].y;
		temp.z = (holes[count + 3].z - holes[count + 1].z) / 2 + holes[count + 1].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(1)=>(4) middle hole -> uprow middle
		temp.x = (holes[count + 4].x - holes[count + 1].x) / 2 + holes[count + 1].x;
		temp.y = (holes[count + 4].y - holes[count + 1].y) / 2 + holes[count + 1].y;
		temp.z = (holes[count + 4].z - holes[count + 1].z) / 2 + holes[count + 1].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(1)=>(2) middle hole -> right same row
		temp.x = (holes[count + 2].x - holes[count + 1].x) / 2 + holes[count + 1].x;
		temp.y = (holes[count + 2].y - holes[count + 1].y) / 2 + holes[count + 1].y;
		temp.z = (holes[count + 2].z - holes[count + 1].z) / 2 + holes[count + 1].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(2)=>(4) right hole -> uprow middle hole
		temp.x = (holes[count + 4].x - holes[count + 2].x) / 2 + holes[count + 2].x;
		temp.y = (holes[count + 4].y - holes[count + 2].y) / 2 + holes[count + 2].y;
		temp.z = (holes[count + 4].z - holes[count + 2].z) / 2 + holes[count + 2].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(2)=>(5) right hole -> uprow right hole
		temp.x = (holes[count + 5].x - holes[count + 2].x) / 2 + holes[count + 2].x;
		temp.y = (holes[count + 5].y - holes[count + 2].y) / 2 + holes[count + 2].y;
		temp.z = (holes[count + 5].z - holes[count + 2].z) / 2 + holes[count + 2].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		myfile << "\n Count " << count << "\t Lights Size " << holes.size() << "\n";

		if (count < stop && count > stop - 6) {
			//Fill in last row of fake holes
			myfile << "\nFill last row of fake holes";
			//(3)=>(4) up left -> up middle
			temp.x = (holes[count + 4].x - holes[count + 3].x) / 2 + holes[count + 3].x;
			temp.y = (holes[count + 4].y - holes[count + 3].y) / 2 + holes[count + 3].y;
			temp.z = (holes[count + 4].z - holes[count + 3].z) / 2 + holes[count + 3].z;
			holes.push_back(temp);
			myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

			//(4)=>(5) up middle -> up right
			temp.x = (holes[count + 5].x - holes[count + 4].x) / 2 + holes[count + 4].x;
			temp.y = (holes[count + 5].y - holes[count + 4].y) / 2 + holes[count + 4].y;
			temp.z = (holes[count + 5].z - holes[count + 4].z) / 2 + holes[count + 4].z;
			holes.push_back(temp);
			myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
			myfile << "\n Count " << count << "\t Lights Size " << holes.size() << "\n";
		}
	}


}

void makeRandomHoles(double num, double size) {
	temp.dia = size;
	temp.isReal = true;
	for (int  count = 0; count < num; count++) {
		//Pick Random X, Y & Z 3Dpoints
		//myfile << "\nCheck out Random Temp Light Hole";
		degrees = rand() % 360;
		temp.x = (double)(rand() % (int)(_poleLength - _gapBottom - _gapTop)) + _gapBottom;
		temp.y = cos(degrees) * _radius;
		temp.z = sin(degrees) * _radius;
		myfile << "\n[temp]\t" << temp.x << "\t" << temp.y << "\t" << temp.z << "\t" << temp.dia << "\t" << temp.isReal;
		//Check random point distance to all other current points
		for (int x = 0; x < holes.size(); x++) {
			if (sqrt(pow(temp.x - holes[x].x, 2) + pow(temp.y - holes[x].y, 2) + pow(temp.z - holes[x].z, 2)) > _bitL*2.5) {
				holes.push_back(temp);
				myfile << "\n[" << holes.size() << "][" << x << "] Degrees " << degrees << "\t" << temp.x << "\t" << temp.y << "\t" << temp.z << "\t" << temp.dia << "\t" << temp.isReal;
				break;
			}
		}
	}
}


void drillHole(double x, double y, double z, double drillBit) {
	Ptr<Design> design = app->activeProduct();
	Ptr<Component> rootComp = design->rootComponent();
	Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();
	Ptr<ConstructionPlaneInput> planeInput = planes->createInput();

	Ptr<BRepBodies> bodies = rootComp->bRepBodies();
	Ptr<BRepBody> body = bodies->item(0);
	Ptr<BRepFaces> faces = body->faces();
	Ptr<BRepFace> cylinderFace;
	for (auto face : faces)
	{
		Ptr<Cylinder> cylinder = face->geometry();
		if (cylinder && std::fabs(cylinder->radius() - _poleOD) < 1.0e-6)
		{
			cylinderFace = face;
			break;
		}
	}

	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());
	Ptr<SketchPoints> points = sketch->sketchPoints();
	Ptr<Point3D> pickPt = Point3D::create(x, y, z);
	Ptr<SketchPoint> pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));
	planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
	Ptr<ConstructionPlane> plane = planes->add(planeInput);

	// Create a hole input
	double stroke = 1;
	Ptr<Features> features = rootComp->features();
	Ptr<HoleFeatures> holes = features->holeFeatures();
	Ptr<HoleFeatureInput> holeInput = holes->createSimpleInput(ValueInput::createByReal(drillBit)); // If you use a variable you don't get a hole
	holeInput->setPositionByPoint(plane, Point3D::create(x, y, z));
	holeInput->setDistanceExtent(adsk::core::ValueInput::createByReal(_poleOD / 2));
	Ptr<HoleFeature> hole = holes->add(holeInput);
}

extern "C" XI_EXPORT bool run(const char* context)
{
	myfile.open("debug033101.txt");
	srand((unsigned)time(NULL));
	myfile << std::to_string(rand()) + " Random Initialized\n";
	myfile << M_PI << " Pi works\n";

	
	//hole temp;
	temp.x = _gapBottom + _bitL / 2;
	temp.y = cos(degrees);
	temp.z = sin(degrees);
	temp.dia = _bitL;
	temp.isReal = true;
	myfile << temp.x << "\t" << temp.y << "\t" << temp.z << "\t" << temp.dia << "\t" << temp.isReal;
	myfile << "OK - Variable Initialization\n";

	if (!createToolBody()) return false;
	myfile << "OK - Created Pole\n";

	makeCylinder();
	myfile << "OK - Created Cylinder\n";

	makeCandyCane();

	makePhantomHoles();

	makeRandomHoles(_numHolesL, _bitL);
	makeRandomHoles(_numHolesM, _bitM);
	makeRandomHoles(_numHolesS, _bitS);

	//Pop drill stack
	for (int count = 0; count < holes.size(); count++) {
		if (holes[count].isReal == true) {
			drillHole(holes[count].x, holes[count].y, holes[count].z, holes[count].dia);
			myfile << "[" << count << "] Popped\t" << holes[count].x << "\t" << holes[count].y << "\t" << holes[count].z << "\n";
		}
	}/*
	for (int count = 405; count <455; count++) {
		if (holes[count].isReal == false) {
			drillHole(holes[count].x, holes[count].y, holes[count].z, holes[count].dia);
			myfile << "[" << count << "] Popped\t" << holes[count].x << "\t" << holes[count].y << "\t" << holes[count].z << "\n";
		}
	}*/
	/*
	for (int count = 1350; count <1450; count++) {
		if (holes[count].isReal == true) {
			drillHole(holes[count].x, holes[count].y, holes[count].z, holes[count].dia);
			myfile << "[" << count << "] Popped\t" << holes[count].x << "\t" << holes[count].y << "\t" << holes[count].z << "\n";
		}
	}*/


	return true;
}

#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN
Message 19 of 23
marshaltu
in reply to: kevin

Hello,

 

If the crash was because of capacity, I modified the script a little bit. For example: avoid to create sketch for every point, delete work plane/sketch point after hole is created. Please give a try and see if it makes any difference? 

 

BTW: the performance would be worse because more cleanup codes will be executed.

 

Thanks,

Marshal

 

#define _USE_MATH_DEFINES

#include <Core/CoreAll.h>
#include <Fusion/FusionAll.h>
#include <CAM/CAMAll.h>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <stack>
#include <random>
#include <vector>

using namespace adsk::core;
using namespace adsk::fusion;
using namespace adsk::cam;
using namespace std;

ofstream myfile;

struct hole {
	double x, y, z, dia;
	bool isReal;
};
vector<hole> holes;
hole temp;

double degrees = 0;

double _poleLength = 2.54 * 8 * 12;
double _gapTop = 2.54 * 6;
double _gapBottom = 2.54 * 6;
double _poleOD = 2.54 * 1;
double _poleID = 2.54 * .75;
double _slices = 12;
double _sliceArcLength = M_PI * _poleOD / _slices;
double _radius = _poleOD / 2;
double _bitL = 2.54 * 5 / 16;
double _bitM = 2.54 * 1 / 4;
double _bitS = 2.54 * 3 / 16;
int _numHolesL = 2000;
int _numHolesM = 1500;
int _numHolesS = 1000;

Ptr<Application> app = Application::get();
Ptr<UserInterface> ui = app->userInterface();

bool createToolBody()
{
	Ptr<Documents> docs = app->documents();

	// Create a document.
	Ptr<Document> doc = docs->add(DocumentTypes::FusionDesignDocumentType);
	Ptr<Design> design = app->activeProduct();
	design->designType(adsk::fusion::DesignTypes::DirectDesignType);

	// Get the root component of the active design
	Ptr<Component> rootComp = design->rootComponent();

	// Create sketch
	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->add(rootComp->yZConstructionPlane());

	// Create sketch circle
	Ptr<SketchCurves> curves = sketch->sketchCurves();
	Ptr<SketchCircles> circles = curves->sketchCircles();
	Ptr<Point3D> centerPoint = Point3D::create(0, 0, 0);
	circles->addByCenterRadius(centerPoint, _poleID);
	circles->addByCenterRadius(centerPoint, _poleOD);

	// Get the profile defined by the circle
	Ptr<Profiles> profs = sketch->profiles();
	Ptr<Profile> prof = profs->item(1);

	//// Create an extrusion input
	Ptr<Features> features = rootComp->features();
	Ptr<ExtrudeFeatures> extrudes = features->extrudeFeatures();
	Ptr<ExtrudeFeatureInput> extInput = extrudes->createInput(prof, FeatureOperations::NewBodyFeatureOperation);

	// Define that the extent is a distance extent of 8 ft
	Ptr<ValueInput> distance = ValueInput::createByReal(_poleLength);

	// Set the distance extent to be one-way symmetric
	extInput->setDistanceExtent(false, distance);

	// Set the extrude to be a solid one
	extInput->isSolid(true);

	// Create an cylinder
	Ptr<ExtrudeFeature> extrude = extrudes->add(extInput);

	return true;
}


/*
void drillHole(double x, double y, double z) {

Ptr<Design> design = app->activeProduct();
Ptr<Component> rootComp = design->rootComponent();
Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();

Ptr<SketchPoints> points = sketch->sketchPoints();


//Create new plane hole
planes->createInput();
Ptr<Point3D>pickPt = Point3D::create(x, y, z);
//points->release();
Ptr<SketchPoint>pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));
planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
plane = planes->add(planeInput);
holeInput->setPositionByPoint(plane, Point3D::create(x, y, z));
holes->add(holeInput);
}
*/


void makeCandyCane() {
	//Candy Cane Coordinated
	for (temp.x = _gapBottom; temp.x <= _poleLength - _gapTop; temp.x += _bitL) {
		temp.y = cos(degrees);
		temp.z = sin(degrees);
		holes.push_back(temp);
		//holes.pop_back();
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
		temp.y = cos(degrees + .5);
		temp.z = sin(degrees + .5);
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
		temp.y = cos(degrees + 1);
		temp.z = sin(degrees + 1);
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
		temp.x += _bitL;
		degrees += .25;
	}myfile << "\nOK - Candy Cane\n";
}

void makePhantomHoles() {
	//Create Phantom Candy Cane Holes
	myfile << "Create Phantom Holes\n";
	temp.isReal = false;
	double stop = (double)holes.size() - 3;

	for (int count = 0; count < stop; count += 3)
	{
		//(0)=>(1) left hole -> middle hole same row
		temp.x = (holes[count + 1].x - holes[count].x) / 2 + holes[count].x;
		temp.y = (holes[count + 1].y - holes[count].y) / 2 + holes[count].y;
		temp.z = (holes[count + 1].z - holes[count].z) / 2 + holes[count].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(0)=>(3) left hole -> uprow left
		temp.x = (holes[count + 3].x - holes[count].x) / 2 + holes[count].x;
		temp.y = (holes[count + 3].y - holes[count].y) / 2 + holes[count].y;
		temp.z = (holes[count + 3].z - holes[count].z) / 2 + holes[count].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(1)=>(3) middle hole -> uprow left
		temp.x = (holes[count + 3].x - holes[count + 1].x) / 2 + holes[count + 1].x;
		temp.y = (holes[count + 3].y - holes[count + 1].y) / 2 + holes[count + 1].y;
		temp.z = (holes[count + 3].z - holes[count + 1].z) / 2 + holes[count + 1].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(1)=>(4) middle hole -> uprow middle
		temp.x = (holes[count + 4].x - holes[count + 1].x) / 2 + holes[count + 1].x;
		temp.y = (holes[count + 4].y - holes[count + 1].y) / 2 + holes[count + 1].y;
		temp.z = (holes[count + 4].z - holes[count + 1].z) / 2 + holes[count + 1].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(1)=>(2) middle hole -> right same row
		temp.x = (holes[count + 2].x - holes[count + 1].x) / 2 + holes[count + 1].x;
		temp.y = (holes[count + 2].y - holes[count + 1].y) / 2 + holes[count + 1].y;
		temp.z = (holes[count + 2].z - holes[count + 1].z) / 2 + holes[count + 1].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(2)=>(4) right hole -> uprow middle hole
		temp.x = (holes[count + 4].x - holes[count + 2].x) / 2 + holes[count + 2].x;
		temp.y = (holes[count + 4].y - holes[count + 2].y) / 2 + holes[count + 2].y;
		temp.z = (holes[count + 4].z - holes[count + 2].z) / 2 + holes[count + 2].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		//(2)=>(5) right hole -> uprow right hole
		temp.x = (holes[count + 5].x - holes[count + 2].x) / 2 + holes[count + 2].x;
		temp.y = (holes[count + 5].y - holes[count + 2].y) / 2 + holes[count + 2].y;
		temp.z = (holes[count + 5].z - holes[count + 2].z) / 2 + holes[count + 2].z;
		holes.push_back(temp);
		myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

		myfile << "\n Count " << count << "\t Lights Size " << holes.size() << "\n";

		if (count < stop && count > stop - 6) {
			//Fill in last row of fake holes
			myfile << "\nFill last row of fake holes";
			//(3)=>(4) up left -> up middle
			temp.x = (holes[count + 4].x - holes[count + 3].x) / 2 + holes[count + 3].x;
			temp.y = (holes[count + 4].y - holes[count + 3].y) / 2 + holes[count + 3].y;
			temp.z = (holes[count + 4].z - holes[count + 3].z) / 2 + holes[count + 3].z;
			holes.push_back(temp);
			myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;

			//(4)=>(5) up middle -> up right
			temp.x = (holes[count + 5].x - holes[count + 4].x) / 2 + holes[count + 4].x;
			temp.y = (holes[count + 5].y - holes[count + 4].y) / 2 + holes[count + 4].y;
			temp.z = (holes[count + 5].z - holes[count + 4].z) / 2 + holes[count + 4].z;
			holes.push_back(temp);
			myfile << "\n[" << holes.size() - 1 << "]\t" << holes[holes.size() - 1].x << "\t" << holes[holes.size() - 1].y << "\t" << holes[holes.size() - 1].z << "\t" << holes[holes.size() - 1].dia << "\t" << holes[holes.size() - 1].isReal;
			myfile << "\n Count " << count << "\t Lights Size " << holes.size() << "\n";
		}
	}


}

void makeRandomHoles(double num, double size) {
	temp.dia = size;
	temp.isReal = true;
	for (int count = 0; count < num; count++) {
		//Pick Random X, Y & Z 3Dpoints
		//myfile << "\nCheck out Random Temp Light Hole";
		degrees = rand() % 360;
		temp.x = (double)(rand() % (int)(_poleLength - _gapBottom - _gapTop)) + _gapBottom;
		temp.y = cos(degrees) * _radius;
		temp.z = sin(degrees) * _radius;
		myfile << "\n[temp]\t" << temp.x << "\t" << temp.y << "\t" << temp.z << "\t" << temp.dia << "\t" << temp.isReal;
		//Check random point distance to all other current points
		for (int x = 0; x < holes.size(); x++) {
			if (sqrt(pow(temp.x - holes[x].x, 2) + pow(temp.y - holes[x].y, 2) + pow(temp.z - holes[x].z, 2)) > _bitL*2.5) {
				holes.push_back(temp);
				myfile << "\n[" << holes.size() << "][" << x << "] Degrees " << degrees << "\t" << temp.x << "\t" << temp.y << "\t" << temp.z << "\t" << temp.dia << "\t" << temp.isReal;
				break;
			}
		}
	}
}


void drillHole(double x, double y, double z, double drillBit) {
	Ptr<Design> design = app->activeProduct();
	Ptr<Component> rootComp = design->rootComponent();
	Ptr<ConstructionPlanes> planes = rootComp->constructionPlanes();
	Ptr<ConstructionPlaneInput> planeInput = planes->createInput();

	Ptr<BRepBodies> bodies = rootComp->bRepBodies();
	Ptr<BRepBody> body = bodies->item(0);
	Ptr<BRepFaces> faces = body->faces();
	Ptr<BRepFace> cylinderFace;
	for (auto face : faces)
	{
		Ptr<Cylinder> cylinder = face->geometry();
		if (cylinder && std::fabs(cylinder->radius() - _poleOD) < 1.0e-6)
		{
			cylinderFace = face;
			break;
		}
	}

	Ptr<Sketches> sketches = rootComp->sketches();
	Ptr<Sketch> sketch = sketches->itemByName("holePoints");
	if (!sketch)
	{
		sketch = sketches->add(rootComp->yZConstructionPlane());
		sketch->name("holePoints");
	}
	Ptr<SketchPoints> points = sketch->sketchPoints();
	Ptr<Point3D> pickPt = Point3D::create(x, y, z);
	Ptr<SketchPoint> pickSketchPt = points->add(sketch->modelToSketchSpace(pickPt));
	planeInput->setByTangentAtPoint(cylinderFace, pickSketchPt);
	Ptr<ConstructionPlane> plane = planes->add(planeInput);

	// Create a hole input
	double stroke = 1;
	Ptr<Features> features = rootComp->features();
	Ptr<HoleFeatures> holes = features->holeFeatures();
	Ptr<HoleFeatureInput> holeInput = holes->createSimpleInput(ValueInput::createByReal(drillBit)); // If you use a variable you don't get a hole
	holeInput->setPositionByPoint(plane, Point3D::create(x, y, z));
	holeInput->setDistanceExtent(adsk::core::ValueInput::createByReal(_poleOD / 2));
	Ptr<HoleFeature> hole = holes->add(holeInput);

	plane->deleteMe();
	pickSketchPt->deleteMe();
}

extern "C" XI_EXPORT bool run(const char* context)
{
	myfile.open("debug033101.txt");
	srand((unsigned)time(NULL));
	myfile << std::to_string(rand()) + " Random Initialized\n";
	myfile << M_PI << " Pi works\n";


	//hole temp;
	temp.x = _gapBottom + _bitL / 2;
	temp.y = cos(degrees);
	temp.z = sin(degrees);
	temp.dia = _bitL;
	temp.isReal = true;
	myfile << temp.x << "\t" << temp.y << "\t" << temp.z << "\t" << temp.dia << "\t" << temp.isReal;
	myfile << "OK - Variable Initialization\n";

	if (!createToolBody()) return false;
	myfile << "OK - Created Pole\n";

	myfile << "OK - Created Cylinder\n";

	makeCandyCane();

	makePhantomHoles();

	makeRandomHoles(_numHolesL, _bitL);
	makeRandomHoles(_numHolesM, _bitM);
	makeRandomHoles(_numHolesS, _bitS);

	//Pop drill stack
	for (int count = 0; count < holes.size(); count++) {
		if (holes[count].isReal == true) {
			drillHole(holes[count].x, holes[count].y, holes[count].z, holes[count].dia);
			myfile << "[" << count << "] Popped\t" << holes[count].x << "\t" << holes[count].y << "\t" << holes[count].z << "\n";
		}
	}/*
	 for (int count = 405; count <455; count++) {
	 if (holes[count].isReal == false) {
	 drillHole(holes[count].x, holes[count].y, holes[count].z, holes[count].dia);
	 myfile << "[" << count << "] Popped\t" << holes[count].x << "\t" << holes[count].y << "\t" << holes[count].z << "\n";
	 }
	 }*/
	 /*
	 for (int count = 1350; count <1450; count++) {
	 if (holes[count].isReal == true) {
	 drillHole(holes[count].x, holes[count].y, holes[count].z, holes[count].dia);
	 myfile << "[" << count << "] Popped\t" << holes[count].x << "\t" << holes[count].y << "\t" << holes[count].z << "\n";
	 }
	 }*/


	return true;
}

#ifdef XI_WIN

#include <windows.h>

BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID reserved)
{
	switch (reason)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

#endif // XI_WIN


Marshal Tu
Fusion 360 Developer
Autodesk, Inc.

Message 20 of 23
kevin
in reply to: marshaltu

That almost worked.

 

However only 4400 of the holes were made out of 5844 that it should have.

It's such a round number, Is this a software limit?
Ugh

 

Limit.png

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report