def CheckPointConstraints(csg_file, pos_points, neg_points): # Save positive and negative points into temporary files. tmp_pos_file = os.path.join(csg_output_dir, '.pos.data') tmp_neg_file = os.path.join(csg_output_dir, '.neg.data') tmp_point_file = os.path.join(csg_output_dir, '.point.data') # Check positive points first. helper.SaveDataFile(tmp_point_file, pos_points) helper.Run('%s csg-flag -d %s -e %f -i %s -n %s -p %s' % \ (os.environ['CSG_CPP_EXE'], tmp_point_file, 0, csg_file, \ tmp_neg_file, tmp_pos_file)) unsatisfied_pos = helper.LoadDataFile(tmp_neg_file) # Check if some points are missing. satisfied_pos = helper.LoadDataFile(tmp_pos_file) if satisfied_pos.shape[0] + unsatisfied_pos.shape[0] != pos_points.shape[0]: helper.PrintWithRedColor('Error: some pos constraints are ignored.') # Then check negative points. helper.SaveDataFile(tmp_point_file, neg_points) helper.Run('%s csg-flag -d %s -e %f -i %s -n %s -p %s' % \ (os.environ['CSG_CPP_EXE'], tmp_point_file, 0, csg_file, \ tmp_neg_file, tmp_pos_file)) unsatisfied_neg = helper.LoadDataFile(tmp_pos_file) # Check if some points are missing. satisfied_neg = helper.LoadDataFile(tmp_neg_file) if satisfied_neg.shape[0] + unsatisfied_neg.shape[0] != neg_points.shape[0]: helper.PrintWithRedColor('Error: some neg constraints are ignored.') os.remove(tmp_pos_file) os.remove(tmp_neg_file) os.remove(tmp_point_file) return unsatisfied_pos, unsatisfied_neg
def ReadPrimitiveFile(primitive_file): spheres = [] planes = [] cylinders = [] tori = [] for line in open(primitive_file).readlines(): info = line.strip().split() name = info[0] params = [float(x) for x in info[1:]] if name == 'sphere': spheres.append(MakeSphere(params)) elif name == 'plane': planes.append(MakePlane(params)) elif name == 'cylinder': cylinders.append(MakeCylinder(params)) elif name == 'torus': tori.append(MakeTorus(params)) else: helper.PrintWithRedColor('Unsupported primitive type: %s' % name) sys.exit(-1) print('Spheres (%d): ' % len(spheres)) PrettyPrintList(spheres) print('Planes (%d): ' % len(planes)) PrettyPrintList(planes) print('Cylinders (%d): ' % len(cylinders)) PrettyPrintList(cylinders) print('Tori (%d): ' % len(tori)) PrettyPrintList(tori) return spheres, planes, cylinders, tori
helper.Run('sudo hg clone https://bitbucket.org/gatoatigrado/sketch-frontend') helper.Run('sudo mv sketch-frontend sketch-frontend-default') # Use this version of sketch. helper.Run('sudo hg clone -r 2c8b363 sketch-frontend-default sketch-frontend') sketch_frontend_folder = os.path.join(sketch_folder, 'sketch-frontend') env_variables['CSG_SKETCH_FRONTEND'] = sketch_frontend_folder os.chdir(sketch_frontend_folder) shutil.copyfile(os.path.join(root_folder, 'pom.xml'), \ os.path.join(sketch_frontend_folder, 'pom.xml')) helper.Run( 'sudo make system-install DESTDIR=/usr/bin SUDOINSTALL=1 -w --no-print-directory -s' ) # Now check Sketch again. if not CheckSketch(): helper.PrintWithRedColor('Failed to install Sketch. Please fix.') sys.exit(-1) SaveCustomizedEnvironmentVariables(env_variables, os.path.join(build_folder, 'ENVIRONMENT')) ################################################################################ # Tests on samples ################################################################################ # Check on example file from CSGInverse samples os.chdir(root_folder) # Decomment this code if you RAM can handle these calculations # helper.RunWithStdout('sudo python3 run_tests.py build ex_140') # Check csg_cpp_command
def SolveOnePart(idx, all_pos_constraints, all_neg_constraints, primitive_roi, \ mesh_info): # Call this function to solve all_pos_constraints and all_neg_constraints # using primitives inside primitive_roi. # Returns a string that describes the csg tree, and done to indicate whether # the problem is solved. # Call Sketch to satisfy pos_constraints and neg_constraints. xmin, xmax, ymin, ymax, zmin, zmax = primitive_roi helper.PrintWithGreenColor('Part %d, roi (%f, %f, %f, %f, %f, %f)' \ % (idx, xmin, xmax, ymin, ymax, zmin, zmax)) print('Constraints: %d positive, %d negative.' % \ (all_pos_constraints.shape[0], all_neg_constraints.shape[0])) # Save them for debugging purposes. They are duplicated in data.sk. pos_constraints_file = os.path.join(point_output_dir, 'pos_%d.data' % idx) helper.SaveDataFile(pos_constraints_file, all_pos_constraints) neg_constraints_file = os.path.join(point_output_dir, 'neg_%d.data' % idx) helper.SaveDataFile(neg_constraints_file, all_neg_constraints) # Prepare the data file. sketch_data_file = os.path.join(sketch_harness_dir, 'data_%d.sk' % idx) sketch_idx_file = os.path.join(sketch_harness_dir, 'idx_%d.sk' % idx) helper.SavePointToSketch(sketch_data_file, sketch_idx_file, \ all_pos_constraints, all_neg_constraints) # Prepare the primitive file. prim_file = os.path.join(point_output_dir, 'surface_primitives_%d.prim' % idx) unsat_code = 1 def UnsatHandler(command, exit_code): if exit_code != unsat_code: helper.DefaultExceptionHandle(command, exit_code) else: helper.PrintWithGreenColor('UNSAT detected.') while True: xmin, xmax, ymin, ymax, zmin, zmax = primitive_roi helper.Run('%s primitive-local -p %s -o %s -i %s -s %f %f %f %f %f %f' % ( \ os.environ['CSG_CPP_EXE'], mesh_info['primitive_file'], prim_file, \ '.dummy.meta', xmin, xmax, ymin, ymax, zmin, zmax)) # See if the problem is SAT. code = helper.Run('%s remove-prim -e %f -i %s -o %s -n %s -p %s -v' % ( \ os.environ['CSG_CPP_EXE'], eps, prim_file, prim_file, \ neg_constraints_file, pos_constraints_file), UnsatHandler) if code == 0: break elif code == unsat_code: # Try to enlarge the roi. if Enclose(primitive_roi, mesh_info['bounding_box']): helper.PrintWithRedColor('Roi is already larger than the bounding ' \ 'box but the problem is still UNSAT. Should never happen.') sys.exit(-1) helper.PrintWithGreenColor( 'Enlarge the primitive roi and retry...') primitive_roi = EnlargeBoundingBox(primitive_roi, 1.1) else: # Should never happen. helper.PrintWithRedColor('See exit code other than 1. ' \ 'Should never happen.') sys.exit(-1) # Now the surface primitives are stored in prim_file and all of them are # necessary. We can count the number of solid primitives and terminate it # early if we are sure the solution is too big for sketch to solve. estimated_prim_num = \ surface_primitive_to_sketch.CountMinimumNumberOfSolidPrimitives(prim_file) if estimated_prim_num > max_prim_num: # Call segmentation. helper.PrintWithRedColor('Problem seems to require a deeper CSG tree. ' \ 'Call segmentation.') return '', False prim_sketch_file = os.path.join(sketch_harness_dir, \ 'primitives_%d.sk' % idx) surface_primitive_to_sketch.WriteSurfacePrimitivesToSolidSketch( \ prim_file, prim_sketch_file, mesh_info['max_offsets'] + 10 * eps) sketch_harness_file_name = '%s_%d' % (output_dir.split('/')[-1], idx) sketch_harness_file = os.path.join(sketch_harness_dir, \ sketch_harness_file_name) + '.sk' sketch_solver_file = os.path.join(sketch_harness_dir, \ 'csg_solver_%d.sk' % idx) # Sketch harness file. CreateSketch(sketch_harness_file, sketch_solver_file, \ os.path.basename(sketch_data_file), sketch_idx_file, \ os.path.basename(prim_sketch_file)) # Run Sketch and get its log. sketch_output_file = os.path.join(sketch_output_dir, \ sketch_harness_file_name + '.log') sketch_done = GetSketch(sketch_harness_file, sketch_output_file, \ timeout) # Check if it succeeded. if not sketch_done or '[SKETCH] DONE' not in open( sketch_output_file).read(): helper.PrintWithRedColor('Problem is too hard. Need segmentation.') return '', False helper.PrintWithGreenColor('Sketch succeeded.') # Display the solution. sketch_solution = GetSketchCompile(sketch_harness_file) # Save the results into a scad file. csg_file = os.path.join(csg_output_dir, 'csg_%d.scad' % idx) f = open(csg_file, 'w') f.write(sketch_solution) f.close() # As a sanity check. unsatisfied_pos, unsatisfied_neg = CheckPointConstraints(csg_file, \ all_pos_constraints, all_neg_constraints) if unsatisfied_pos.size + unsatisfied_neg.size > 0: helper.PrintWithRedColor('Still see unsatisfied constraints. ' \ 'Should never happen.') sys.exit(-1) # Done. return sketch_solution, True
def SetupSketchPipeline(args): global num_counter_samples global eps global num_init_samples global max_iter global mesh_file_loc global surface_density global seg_num global timeout global volume_density global output_dir global sketch_output_dir global point_output_dir global csg_output_dir global sketch_harness_dir build_dir = os.path.realpath(args.builddir) num_counter_samples = int(args.countersample) eps = float(args.eps) num_init_samples = int(args.initsample) max_iter = int(args.max_iter) mesh_file_loc = os.path.realpath(args.mesh) method = args.method output_dir = os.path.realpath(args.outdir) surface_density = float(args.surfacedensity) seg_num = int(args.seg) timeout = int(args.timeout) volume_density = float(args.volumedensity) # Check arguments. if not os.path.exists(build_dir): helper.PrintWithRedColor('Build dir does not exist.') sys.exit(-1) if num_counter_samples <= 0: print('Warning: countersample too small. Using 100 instead.') num_counter_samples = 100 if eps < 1e-3: print('Warning: eps too small. Using 1e-3 instead.') eps = 1e-3 if num_init_samples <= 0: print('Warning: initsample too small. Using 1000 instead.') num_init_samples = 1000 if max_iter <= 0: print('Warning: invalid max iter. Use 10 instead.') max_iter = 10 if not os.path.isfile(mesh_file_loc): helper.PrintWithRedColor('Mesh file does not exist.') sys.exit(-1) if method != 'sketch': helper.PrintWithRedColor('Method should be sketch.') sys.exit(-1) if not os.path.exists(output_dir): os.makedirs(output_dir) if surface_density <= 0: print('Warning: invalid surface density. Use 10000 instead.') sample_density = 10000 if seg_num <= 1: print('Warning: invalid seg num. Use 2 instead.') seg_num = 2 if timeout <= 0: print('Warning: invalid timeout. Use 600 instead.') timeout = 600 if volume_density <= 0: print('Warning: invalid volume density. Use 1000 instead.') volume_density = 1000 helper.PrintWithGreenColor('All arguments seem reasonable.') # Set up folders. sketch_output_dir = os.path.join(output_dir, 'sketch_output') if not os.path.exists(sketch_output_dir): os.makedirs(sketch_output_dir) point_output_dir = os.path.join(output_dir, 'points') if not os.path.exists(point_output_dir): os.makedirs(point_output_dir) csg_output_dir = os.path.join(output_dir, 'csg') if not os.path.exists(csg_output_dir): os.makedirs(csg_output_dir) sketch_harness_dir = os.path.join(output_dir, 'sketches') if not os.path.exists(sketch_harness_dir): os.makedirs(sketch_harness_dir)
parser.add_argument('--outdir', help='a folder to store all results', default='../one_cube/') parser.add_argument('--surfacedensity', help='number of samples in unit ' \ 'volume in the surface shell', default=10000) parser.add_argument('--seg', help='number of segmentations', default=2) parser.add_argument('--timeout', help='max allowable time in seconds for '\ 'each sketch call.', default=600) parser.add_argument('--volumedensity', help='number of samples in unit ' \ 'volume, used to segment the mesh.', default=1000) args = parser.parse_args() # Load environment variables. env_file = os.path.join(os.path.realpath(args.builddir), 'ENVIRONMENT') for line in open(env_file): if '#' not in line: key, value = line.strip().split() os.environ[key[:-1]] = value.strip() if __name__ == '__main__': if args.method == 'sketch': sketch_pipeline.SetupSketchPipeline(args) sketch_pipeline.RunSketchPipeline() elif args.method == 'genetic': # import genetic_algorithm_pipeline # genetic_algorithm_pipeline.SetupGeneticAlgorithmPipeline(args) # genetic_algorithm_pipeline.RunGeneticAlgorithmPipeline() raise NotImplementedError('genetic_algorithm_pipeline not implemented!') else: helper.PrintWithRedColor('Invalid method: %s' % args.method) sys.exit(-1)
def main(): parser = argparse.ArgumentParser() parser.add_argument('-d', '--build_dir', default='', help='build directory path.') parser.add_argument('-dp', '--deps', action='store_false', help='Disable apt-get & py3 dependencies.') parser.add_argument('-eg', '--eigen', action='store_false', help='Disable Eigen install.') parser.add_argument('-cg', '--cgal', action='store_false', help='Disable CGAL install.') parser.add_argument('-c', '--cpp', action='store_false', help='Disable source cpp compilation.') parser.add_argument('-sk', '--sketch', action='store_false', help='Disable sketch installation.') args = parser.parse_args() print('Arguments:', args) # Usage: python3 install.py -d <build folder> if not args.build_dir: print('Usage: python3 install.py -d <build_folder>') sys.exit(-1) build_folder = os.path.realpath(args.build_dir) root_folder = HERE if not os.path.exists(build_folder): os.makedirs(build_folder) helper.PrintWithGreenColor('Build folder created :{}'.format(build_folder)) # Add a new environment variable to save the location of the root folder. env_variables['CSG_ROOT'] = os.environ['CSG_ROOT'] = root_folder # Check all C++ dependencies. if args.deps: print('Attempt to install build-essential, autoconf, libtool, flex, bison, ' 'mecurial, zsh, and cmake. Asking for sudo privilege.') # This works for Ubuntu 17.04 and 16.04. exit_code = helper.Run('sudo apt-get install gcc-6 g++-6 -y', None) if exit_code != 0: # This works for Ubuntu 14.04. helper.Run('sudo apt-get update') helper.Run('sudo apt-get install build-essential ' \ 'software-properties-common -y') helper.Run('sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y') helper.Run('sudo apt-get update') helper.Run('sudo apt-get install gcc-snapshot -y') helper.Run('sudo apt-get update') helper.Run('sudo apt-get install gcc-6 g++-6 -y') helper.Run('sudo apt-get install autoconf libtool flex bison ' 'mercurial zsh cmake') # Install python dependencies. helper.Run('python3 -m pip install -U pip setuptools') helper.Run('python3 -m pip install --upgrade pip') helper.Run('python3 -m pip install numpy scipy matplotlib ipython ' 'jupyter pandas sympy nose') helper.Run('python3 -m pip install -U scikit-learn') # Install CGAL. InstallCGAL(build_folder, args.eigen) # Install Eigen-3.3.4. InstallEigen(root_folder, args.cgal) # Compile cpp. if args.cpp: cpp_build_folder = os.path.join(build_folder, 'cpp') if not os.path.exists(cpp_build_folder): os.makedirs(cpp_build_folder) os.chdir(cpp_build_folder) os.environ['CC'] = '/usr/bin/gcc-6' os.environ['CXX'] = '/usr/bin/g++-6' helper.Run('cmake -DCGAL_DIR=%s %s' % (env_variables['CGAL_DIR'], \ os.path.join(root_folder, 'cpp'))) helper.Run('make') helper.PrintWithGreenColor('C++ program compiled successfully.') env_variables['CSG_CPP_EXE'] = os.path.join(cpp_build_folder, 'csg_cpp_command') # Install Sketch. # Try calling Sketch. If it is successful, we are done. if CheckSketch(build_folder): SaveCustomizedEnvironmentVariables(env_variables, os.path.join( build_folder, 'ENVIRONMENT')) helper.PrintWithGreenColor('Installation Done.') sys.exit(0) # If we are here, Sketch is not properly installed. # First, install Oracle JDK 8. print('Attempt to install Oracle JDK 8. Asking for sudo privilege.') InstallJava() # Next, install maven. InstallMaven() # Download sketch-backend. sketch_folder = os.path.join(build_folder, 'sketch') if not os.path.exists(sketch_folder): os.makedirs(sketch_folder) if args.sketch: # Sketch-backend. os.chdir(sketch_folder) helper.Run('hg clone https://bitbucket.org/gatoatigrado/sketch-backend') helper.Run('mv sketch-backend sketch-backend-default') # Use this version of sketch. helper.Run('hg clone -r 04b3403 sketch-backend-default sketch-backend') sketch_backend_folder = os.path.join(sketch_folder, 'sketch-backend') env_variables['CSG_SKETCH_BACKEND'] = sketch_backend_folder if args.sketch: os.chdir(sketch_backend_folder) helper.Run('bash autogen.sh') helper.Run('./configure') helper.Run('make -j2') # Interestingly, I need to manually do the following copy and paste work to # avoid an error in sketch-frontend. sketch_solver_folder = os.path.join(sketch_backend_folder, 'src/SketchSolver') shutil.copyfile(os.path.join(sketch_solver_folder, 'libcegis.a'), \ os.path.join(sketch_solver_folder, '.libs/libcegis.a')) shutil.copyfile(os.path.join(sketch_solver_folder, 'cegis'), \ os.path.join(sketch_solver_folder, '.libs/cegis')) # Download sketch-frontend. os.chdir(sketch_folder) if args.sketch: helper.Run('hg clone https://bitbucket.org/gatoatigrado/sketch-frontend') helper.Run('mv sketch-frontend sketch-frontend-default') # Use this version of sketch. helper.Run('hg clone -r 42c057c sketch-frontend-default sketch-frontend') sketch_frontend_folder = os.path.join(sketch_folder, 'sketch-frontend') env_variables['CSG_SKETCH_FRONTEND'] = sketch_frontend_folder os.chdir(sketch_frontend_folder) if args.sketch: helper.Run('make system-install DESTDIR=/usr/bin SUDOINSTALL=1') # Now check Sketch again. if not CheckSketch(build_folder): helper.PrintWithRedColor('Failed to install Sketch. Please fix.') sys.exit(-1) SaveCustomizedEnvironmentVariables(env_variables, os.path.join( build_folder, 'ENVIRONMENT')) helper.PrintWithGreenColor('Installation Done.')